当前位置: 首页 > news >正文

网络编程,IO多路复用

 

1.使用IO多路复用完成TCP并发服务器

#include<myhead.h>
#define SER_PORT 8888                  //服务器端口号
#define SER_IP  "192.168.124.10"      //服务器IP地址int main(int argc, const char *argv[])
{//1、创建用于连接的套接字int sfd = socket(AF_INET, SOCK_STREAM, 0);  //参数1:通信域,表明使用的是ipv4协议//参数2:通信方式,使用TCP通信//参数3:0表示之前已经指定协议 IPPROTO_TCPif(sfd == -1){perror("socket error");return -1;}printf("sfd = %d\n", sfd);               //3//将端口号快速重用函数int reuse = 1;if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1){perror("setsockopt error");return -1;}printf("端口号快速重用成功\n");//2、给当前套接字绑定IP地址和端口号//2.1填充要绑定的地址信息结构体struct sockaddr_in sin;sin.sin_family =     AF_INET;        //通信域sin.sin_port =         htons(SER_PORT);  //端口号sin.sin_addr.s_addr =     inet_addr(SER_IP);    //ip地址//2.2 绑定if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) == -1){perror("bind error");return -1;}printf("bind success %s %s %d\n", __FILE__, __func__, __LINE__);//3、将套接字设置成监听状态if(listen(sfd, 128) == -1){perror("listen error");return -1;}printf("listen success %s %s %d\n", __FILE__, __func__, __LINE__);//4、阻塞等待客户端的链接请求//4.1定义容器接收客户端的地址信息struct sockaddr_in cin;                  //用于接收地址信息socklen_t socklen = sizeof(cin);          //用于接收地址信息的大小int newfd = -1;//11、准备一个文件描述符容器fd_set readfds, tempfds;          //22、清空容器FD_ZERO(&readfds);//33、将要检测的文件描述符放入集合FD_SET(0, &readfds);FD_SET(sfd, &readfds);//定义一个变量存储容器中最大的文件描述符int maxfd = sfd;//定义一个地址信息结构体数组,每一个元素对应一个客户端文件描述符struct sockaddr_in cin_arr[1024];while(1){tempfds = readfds;   //存储一份数据//使用select函数对容器中的文件描述符进行检测int res = select(maxfd+1,&tempfds,NULL,NULL,NULL);if(res == -1){perror("select error");return -1;}else if(res == 0){printf("timeout\n");return -1;}//判断是否是文件描述符触发事件for(int cli=0;cli<=maxfd;cli++){if(!FD_ISSET(cli,&tempfds)){continue;}if(cli == sfd){//4.2 接收客户端的链接newfd = accept(sfd, (struct sockaddr*)&cin, &socklen);   if(newfd == -1){perror("accept error");return -1;}printf("[%s:%d]发来链接请求 %s %s %d\n", \inet_ntoa(cin.sin_addr), ntohs(cin.sin_port),__FILE__, __func__, __LINE__);//更新地址信息结构体数组cin_arr[newfd] = cin;//将newfd放入readfds中FD_SET(newfd, &readfds);//更新maxfdif(newfd > maxfd){maxfd = newfd;}}else//判断0号文件描述符是否在集合中if(cli == 0){//终端输入char wbuf[128] = "";scanf("%s", wbuf);printf("触发了终端输入事件。。。\n");if(strcmp(wbuf, "quit") == 0){goto END;}//将消息发送给所有客户端for(int i=4; i<=maxfd; i++ ){sendto(i, wbuf, sizeof(wbuf), 0,(struct sockaddr*) &cin_arr[i], sizeof(cin_arr[i]));}}else{//5、跟客户端进行消息通信char buf[128] = "";//将数组清空bzero(buf, sizeof(buf));//读取客户端发来的消息//int res = read(newfd, buf, sizeof(buf));int res = recv(cli, buf, sizeof(buf), 0);if(res == 0){printf("客户端已经下线\n");//关闭当前通信的套接字close(cli);//将当前文件描述符从文件描述符集合中移除FD_CLR(cli, &readfds);//更新maxfdfor(int i=maxfd; i>=sfd; i--){if(FD_ISSET(i, &readfds)){maxfd = i;break;}}continue;}printf("[%s:%d] : %s\n", inet_ntoa(cin_arr[cli].sin_addr), ntohs(cin_arr[cli].sin_port), buf);//给客户端发消息strcat(buf, "*_*");//write(newfd, buf, sizeof(buf));send(cli, buf, sizeof(buf), 0);printf("发送成功\n");}}}END://6、关闭套接字close(sfd);return 0;}

http://www.lryc.cn/news/311874.html

相关文章:

  • 【ue5】滑铲系统蓝图笔记
  • linux系统Jenkins工具参数化构建
  • 生活里的英语应该【怎么说】
  • Centos安装Jenkins
  • 软考中级系统集成必备100题(71-80)真题精炼
  • visual studio的使用
  • 对于爬虫的学习
  • 【学习笔记】开源计算机视觉库OPENCV学习方案
  • LVS负载均衡集群基础概念
  • pwn学习笔记(5)--格式化字符串漏洞(未完全完成)
  • HTML标签之表单标签,web开发实例教程
  • 数据库-第四/五章 数据库安全性和完整性【期末复习|考研复习】
  • 网站维护页面404源码
  • CSS的文本样式属性值,web开发难点
  • springboot+jsp汽车配件管理系统idea maven 项目lw
  • 计算机网络-网络安全(二)
  • Flutter App代码混淆
  • pandas中apply函数的坑——错误信息Must provide ‘func‘ or tuples of ‘(column, aggfunc)的解决办法
  • 《操作系统真相还原》读书笔记二:环境搭建 xshell连接virtualbox
  • CSS盒模型居中方法,大学生必备
  • 【Golang星辰图】构建健壮应用的秘籍:探索Go语言中最强大的测试工具库
  • 刷题笔记day27-回溯算法3
  • 【项目】Boost 搜索引擎
  • vue3 (六)自定义指令
  • vite、mode如果为production打包后 .env.production 中 VITE_API_DOMAIN变量作为API地址吗
  • 静态时序分析:SDC约束命令set_fasle_path详解
  • 浅谈马尔科夫链蒙特卡罗方法(MCMC)算法的理解
  • 2403C++,C++20协程库
  • mybatis动态加载mapper.xml
  • 安卓类加载机制