10.1 国庆节小任务

news2024/11/24 22:51:47

目录

select实现服务器并发

服务器

客户端

运行现象


select实现服务器并发

服务器

#include<myhead.h>

#define PORT 8888             //1024~49151
#define IP "192.168.1.104" //ifconfig查看本机IP

int main(int argc, const char *argv[])
{
    //创建流式套接字
    int sfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sfd < 0)
    {
        ERR_MSG("socket");
        return -1;
    }
    printf("sfd = %d\n", sfd);

    //设置允许端口被快速复用
    int reuse = 1;
    if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
    {
        ERR_MSG("setsockopt");
        return -1;
    }
    printf("允许端口快速重用成功\n");


    //填充地址信息结构体,真实的地址信息结构体根据地址族指定
    //AF_INET: man 7 ip
    struct sockaddr_in sin;
    sin.sin_family      = AF_INET;      //必须填AF_INET
    sin.sin_port        = htons(PORT);  //端口号:1024~49151
    sin.sin_addr.s_addr = inet_addr(IP); //本机IP ifconfig查看

    //绑定服务器的IP和端口--->必须绑定
    if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
    {
        ERR_MSG("bind");
        return -1;
    }
    printf("bind success \n");

    //将套接字设置为被动监听状态
    if(listen(sfd, 128) < 0)
    {
        ERR_MSG("listen");
        return -1;
    }
    printf("listen success\n");

    //创建一个读集合
    fd_set readfds, tempfds;

    //fd_set本质上是一个结构体,成员是一个long类型数组,
    //集合目的是为了存储让内核监测的文件描述符,若不初始化,
    //则有可能随机到有效的但不需要监测的文件描述符,
    //所以需要将集合初始化成无意义的文件描述符
    FD_ZERO(&readfds);
    FD_ZERO(&tempfds);

    //将需要的文件描述符添加到读集合中
    FD_SET(0, &readfds);
    FD_SET(sfd, &readfds);

    int maxfd = sfd;

    int s_res = -1;
    int newfd = -1;
    char buf[128] = "";
    ssize_t res = 0;
    struct sockaddr_in cin;     //存储客户端的地址信息
    socklen_t addrlen = sizeof(cin);

    struct sockaddr_in saveCin[1024-3];

    while(1)
    {
        tempfds = readfds;
        //调用IO多路复用函数 select()
        s_res = select(maxfd+1, &tempfds, NULL, NULL, NULL);
        if(s_res < 0)
        {
            ERR_MSG("select");
            return -1;
        }
        else if(0 == s_res)
        {
            printf("time out...\n");
            break;
        }
        //printf("__%d__\n", __LINE__);

        //能运行到当前位置,则代表集合中有文件描述符准备就绪。
        //此时集合中会只剩下触发事件的文件描述符
        //例如:
        //当0号文件描述符触发事件,则集合中只剩下0
        //当sfd文件描述符触发事件,则集合中只剩下sfd
        //若0和sfd同时触发事件,则集合中剩下0和sfd 

        //判断是哪个文件描述符准备就绪,走对应处理函数即可
        //判断集合中剩下哪个文件描述符,就代表哪个文件描述符准备就绪
        for(int i=0; i<=maxfd; i++)
        {
            if(FD_ISSET(i, &tempfds) == 0)  //若i所代表的文件描述符不在集合中
                continue;                   //则继续遍历下一个i

            //能运行到当前位置,说明i所代表的文件描述符在集合中
            //判断i所代表的文件描述符触发的事件是什么事件
            if(0 == i)
            {
                printf("触发键盘输入事件\n");
                int sndfd = -1;
                res = scanf("%d %s", &sndfd,buf);   //返回值:成功获取到的数据个数
                while(getchar() != 10);
                if(res != 2){
                    printf("请输入正确的格式: fd string\n");
                    continue;
                }

                //能运行到当前位置,则代表输入的格式正确
                if(sndfd<3 || !FD_ISSET(sndfd, &readfds))
                {
                    printf("sndfd=%d 文件描述符错误\n", sndfd);
                    continue;
                }

                if(send(sndfd, buf, sizeof(buf), 0) < 0)
                {
                    ERR_MSG("send");
                    return -1;
                }
                printf("send success\n");
            }
            else if(sfd == i)
            {
                printf("触发客户端连接事件\n");
                newfd = accept(sfd, (struct sockaddr*)&cin, &addrlen);
                if(newfd < 0)
                {
                    ERR_MSG("accept");
                    return -1;
                }
                printf("[%s : %d] newfd=%d 客户端连接成功\n", \
                        inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), newfd);

                saveCin[newfd-3] = cin;

                //将newfd添加到集合中
                FD_SET(newfd, &readfds);

                //更新maxfd
                maxfd = maxfd>newfd ? maxfd:newfd;
            }
            else
            {
                printf("触发客户端交互事件\n");
                bzero(buf, sizeof(buf));
                //接收数据
                res = recv(i, buf, sizeof(buf), 0);
                if(res < 0)
                {
                    ERR_MSG("recv");
                    return -1;
                }
                else if(0 == res)
                {
                    printf("[%s : %d] newfd=%d 客户端下线\n", \
                            inet_ntoa(saveCin[i-3].sin_addr), ntohs(saveCin[i-3].sin_port), i);

                    //关闭下线客户端的文件描述符
                    close(i);
                    //将下线客户端的文件描述符从集合中剔除
                    FD_CLR(i, &readfds);

                    //更新maxfd 
                    //从大往小判断--->从目前记录的最大fd开始判断是否在集合中
                    //若存在,则该文件描述符就是最大的,
                    //若不存在,则继续往小判断
                    while(FD_ISSET(maxfd, &readfds)==0 && maxfd-->=0);

                    /*
                       int j = maxfd;
                       for(; j>=0; j--)
                       {
                       if(FD_ISSET(j, &readfds))
                       break;
                       }
                       maxfd = j;
                       */

                    continue;
                }

                printf("[%s : %d] newfd=%d : %s\n", \
                        inet_ntoa(saveCin[i-3].sin_addr), ntohs(saveCin[i-3].sin_port), i, buf);

                //发送数据
                strcat(buf, "*_*");
                if(send(i, buf, sizeof(buf), 0) < 0)
                {
                    ERR_MSG("send");
                    return -1;
                }
                printf("send success\n");
            }

        }
    } 


    //关闭所有文件描述符
    close(sfd);

    return 0;
}

客户端

#include <myhead.h>

#define PORT 8888             //1024~49151
#define IP "192.168.1.104"

int main(int argc, const char *argv[])
{
	//创建流失套接字
	int cfd=socket(AF_INET,SOCK_STREAM,0);
	if(cfd<0)
	{
		ERR_MSG("socket");
		return -1;
	}
	
	//填充服务器的ip地址信息结构体
	struct sockaddr_in sin;
	sin.sin_family=AF_INET;
	sin.sin_port=htons(PORT);
	sin.sin_addr.s_addr=inet_addr(IP);

	//连接服务器
	if(connect(cfd,(struct sockaddr*)&sin,sizeof(sin))<0)
	{
		ERR_MSG("connect");
		return -1;
	}
	printf("连接服务器成功\n");

	char buf[128];
	//与服务器交互
	while(1)
	{
		bzero(buf,sizeof(buf));
		fgets(buf,sizeof(buf),stdin);
		buf[strlen(buf)-1]='\0';
		if(send(cfd,buf,sizeof(buf),0)<0)
		{
			ERR_MSG("send");
			return -1;
		}
		if(0==strlen(buf))
		{
			break;
		}
		printf("向服务器发送消息成功\n");
		
		bzero(buf,sizeof(buf));
		if(recv(cfd,buf,sizeof(buf),0)<0)
		{
			ERR_MSG("recv");
			return -1;
		}
		printf("服务器:%s\n",buf);

	}
	
	//关闭客户端
	close(cfd);

	return 0;
}

运行现象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1053926.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

1.5.C++项目:仿muduo库实现并发服务器之socket模块的设计

项目完整版在&#xff1a; 一、socket模块&#xff1a;套接字模块 二、提供的功能 Socket模块是对套接字操作封装的一个模块&#xff0c;主要实现的socket的各项操作。 socket 模块&#xff1a;套接字的功能 创建套接字 绑定地址信息 开始监听 向服务器发起连接 获取新连接 …

WPF 02

Grid容器 分行和分列 <Grid><Grid.RowDefinitions><!--2*&#xff1a;此行是下面一行的两倍--><RowDefinition Height"2*"/><RowDefinition/></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition/>…

[管理与领导-107]:IT人看清职场中的隐性规则 - 4 - 职场话术:其实是同一个意思,只是换一种了说法,效果不同,小心被套路

目录 前言&#xff1a; 一、套路和核心思想 1.1 核心思想 1.2 基本原则&#xff1a;让听话者舒服 二、消极变积极的说法 》 自足当下&#xff0c;展望未来 三、委婉拒绝 四、不想接受某项任务 五、正面、让人舒服的表达方式 六、其他 七、职场话术128条&#xff1a;…

ssm+vue的4S店预约保养管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频&#xff1a; ssmvue的4S店预约保养管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结…

淘宝/天猫获得淘宝商品详情API(含测试示例)

taobao.item_get 调用说明 公共参数 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中进入测试&#xff09;secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请求地址中&#xff09;[item_search,item_get,item_search_shop等]c…

智能文字识别技术——AI赋能古彝文保护

前言 人工智能在古彝文古籍保护方面具有巨大的潜力和意义。通过数字化、自动化和智能化的手段&#xff0c;可以更好地保护和传承古彝文的文化遗产&#xff0c;促进彝族文化的传承和发展。 文章目录 前言一、古彝文是什么&#xff1f;1.1古彝文的背景1.2古彝文古籍保护背景 二、…

支持向量机SVM:从数学原理到实际应用

目录 一、引言背景SVM算法的重要性 二、SVM基础线性分类器简介什么是支持向量&#xff1f;超平面和决策边界SVM的目标函数 三、数学背景和优化拉格朗日乘子法&#xff08;Lagrange Multipliers&#xff09;KKT条件核技巧&#xff08;Kernel Trick&#xff09;双重问题和主问题&…

竞赛 基于设深度学习的人脸性别年龄识别系统

文章目录 0 前言1 课题描述2 实现效果3 算法实现原理3.1 数据集3.2 深度学习识别算法3.3 特征提取主干网络3.4 总体实现流程 4 具体实现4.1 预训练数据格式4.2 部分实现代码 5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习机器视觉的…

windows server 2019 、win11安装docker desktop

Docker Desktop Docker Desktop是可以部署在windows运行docker的应用服务&#xff0c;其基于windos的Hyper-V服务和WSL2内核在windos上创建一个子系统(linux)&#xff0c;从而实现其在windows上运行docker。 前提条件 WSL 查看wsl是否安装 我们可以直接在 cmd 或 powershe…

软件过程的介绍

软件过程概述 软件的诞生和生命周期是一个过程&#xff0c;我们总体上称这个过程为软件过程。软件过程是为了开发出软件产品&#xff0c;或者是为了完成软件工程项目而需要完成的有关软件工程的活动&#xff0c;每一项活动又可以分为一系列的工程任务。任何一个软件开发组织&a…

在2023年使用Unity2021从Built-in升级到Urp可行么

因为最近在做WEbgl平台&#xff0c;所以某些不可抗力原因&#xff0c;需要使用Unity2021开发&#xff0c;又由于不可明说原因&#xff0c;想用Urp&#xff0c;怎么办&#xff1f; 目录 创建RenderAsset 关联Asset 暴力转换&#xff08;Menu->Edit&#xff09; 单个文件…

贪心找性质+dp表示+矩阵表示+线段树维护:CF573D

比较套路的题目 首先肯定贪心一波&#xff0c;两个都排序后尽量相连。我一开始猜最多跨1&#xff0c;但其实最多跨2&#xff0c;考虑3个人的情况&#xff1a; 我们发现第3个人没了&#xff0c;所以可以出现跨2的情况 然后直接上dp&#xff0c;由 i − 1 , i − 2 , i − 3 i…

maven无法下载时的解决方法——笔记

右键项目然后点击创建setting.xml&#xff08;因为现在创建了&#xff0c;所以没显示了&#xff0c;可以直接点击打开setting.xml&#xff09; 然后添加 <mirror><id>nexus-aliyun</id><mirrorOf>*,!jeecg,!jeecg-snapshots</mirrorOf><name…

stm32 - GPIO

stm32 - GPIO GPIO结构图GPIO原理图输入上拉/下拉/浮空施密特触发器片上外设 输出推挽/开漏/关闭输出方式 GPIO88种模式复用输出 GPIO寄存器端口配置寄存器_CRL端口输入数据寄存器_IDR端口输出数据寄存器_ODR端口位设置/清除寄存器_BSRR端口位清除寄存器_BRR端口配置锁定寄存器…

《Jetpack Compose从入门到实战》 第二章 了解常用UI组件

目录 常用的基础组件文字组件图片组件按钮组件选择器组件对话框组件进度条组件 常用的布局组件布局Scaffold脚手架 列表 书附代码 Google的图标库 常用的基础组件 文字组件 Composable fun TestText() {Column(modifier Modifier.verticalScroll(state rememberScrollState…

ESP32官方MPU6050组件介绍

前言 &#xff08;1&#xff09;因为我需要使用MPU6050的组件&#xff0c;但是又需要在这条I2C总线上挂载多个设备&#xff0c;所以我本人打算自己对官方的MPU6050的组件进行微调。建立一个I2C总线&#xff0c;设备依赖于这个总线挂载。 &#xff08;2&#xff09;既然要做移植…

list(链表)

文章目录 功能迭代器的分类sort函数&#xff08;排序&#xff09;merage&#xff08;归并&#xff09;unique(去重&#xff09;removesplice&#xff08;转移&#xff09; 功能 这里没有“[]"的实现&#xff1b;原因&#xff1a;实现较麻烦&#xff1b;这里使用迭代器来实…

vue3基础语法

2020年9月18日发布 2022年2月7日称为默认版本&#xff0c;意味vue3是现在也是未来 Ant Design Pc端组件库 Element Plus Pc端组件库 Vant 移动端 VueUse 基于composition 组合式api的常用函数集合 vue3中文文档&#xff1a;https://cn.vuejs.org/guide/introduction.html…

pandas_datareader读取yahoo金融数据超时问题timeout解决方案

在《Python金融数据挖掘》一书中&#xff0c;学习到网络数据源这一章节&#xff0c;利用书中的方法安装了pandas_datareader包&#xff0c;但在获取雅虎数据&#xff08;get_data_yahoo&#xff09;时会出现以下问题&#xff1a; 经过仔细分析和尝试&#xff0c;排除了yahoo受中…

2023年中国智能电视柜产量、需求量、市场规模及行业价格走势[图]

电视柜是随着电视机的发展和普及而演变出的家具种类&#xff0c;其主要作用是承载电视机&#xff0c;又称视听柜&#xff0c;随着生活水平的提高&#xff0c;与电视机相配套的电器设备也成为电视柜的收纳对象。 随着智能家具的发展&#xff0c;智能电视机柜的造型和风格都是有了…