Linux网络编程 - TCP Socket 简单练习:select同时监测多个描述符

2023-05-16

运行方式

服务器端,可以直接运行命令,也可以带参数运行,如果不带参数运行,则程序自主获取主机ip,然后默认设定port和lisnum的值。其中port默认为6666,lisnum默认为5.

[cpp]  view plain  copy  print ? 在CODE上查看代码片 派生到我的代码片
  1. ./socket_select_server IP地址(可选) 端口号(可选)监听队列大小(可选)    
客户端,必须指定服务器的IP地址和端口号,例如:

[cpp]  view plain  copy  print ? 在CODE上查看代码片 派生到我的代码片
  1. ./socket_select_client 172.18.229.60 6666    

服务器代码

[cpp]  view plain  copy  print ? 在CODE上查看代码片 派生到我的代码片
  1. /************************************************************************* 
  2.     > File Name: socket_select_server.c 
  3.     > Author: genglut 
  4.     > Mail: genglut@163.com 
  5.     > Created Time: 2014年12月22日 星期一 18时06分26秒 
  6.  ************************************************************************/  
  7.   
  8. /* 
  9. struct sockaddr_in  
  10. {   
  11.       short int sin_family;                // 地址协议   
  12.       in_port_t sin_port;                  // 端口号   
  13.       struct in_addr sin_addr;           // IP地址  
  14.       unsigned char sin_zero[8];        // 预留位  
  15. };   
  16.  
  17. struct in_addr  
  18. {   
  19.       _u32 s_addr;             // 32位地址   
  20. }; 
  21. */  
  22.   
  23.   
  24. #include <stdio.h>  
  25. #include <stdlib.h>  
  26. #include <errno.h>  
  27. #include <string.h>  
  28. #include <sys/types.h>  
  29. #include <netinet/in.h>  
  30. #include <sys/socket.h>  
  31. #include <sys/wait.h>  
  32. #include <unistd.h>  
  33. #include <arpa/inet.h>  
  34. #include <net/if.h>  
  35. #include <sys/ioctl.h>  
  36.   
  37. #define MAXBUF 1024  
  38.   
  39. void get_ip(char * str, char *ip);//获取本地IP地址  
  40.   
  41. int main(int argc, char *argv[])  
  42. {  
  43.       
  44.     //用于测试命令行输入的值的情况  
  45.     //printf("argv[0] = %s\n", argv[0]);      
  46.     //printf("argv[1] = %s\n", argv[1]);      
  47.     //printf("argv[2] = %s\n", argv[2]);      
  48.     //printf("argv[3] = %s\n", argv[3]);      
  49.   
  50.     int sockfd, newfd;  
  51.     socklen_t len;  
  52.     struct sockaddr_in server_addr, client_addr;//结构体sockaddr_in  
  53.     unsigned int server_port, lisnum;//用int也可以  
  54.     char buf[MAXBUF + 1];  
  55.       
  56.     //下面是select用到的变量的定义  
  57.     fd_set rfds;  
  58.     struct timeval tv;  
  59.     int retval;  
  60.     int maxfd = -1;  
  61.       
  62.     if(argv[1] && argv[2])//要根据argv[1]的情况来判断argv[2]的情况,否则会出错  
  63.         server_port = atoi(argv[2]);  
  64.     else  
  65.         server_port = 6666;  
  66.           
  67.     if(argv[1] && argv[2] && argv[3])//与上面道理相同  
  68.         lisnum = atoi(argv[3]);  
  69.     else  
  70.         lisnum = 5;   
  71.   
  72.     bzero(&server_addr, sizeof(server_addr));//也可以用memset  
  73.     server_addr.sin_family = AF_INET;  
  74.     server_addr.sin_port = htons(server_port);//转换为网络字节序  
  75.       
  76.     if(argv[1])  
  77.         //将ip地址转换为32位网络地址 inet_addr 也可以用inet_aton    
  78.         //inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr);  
  79.         server_addr.sin_addr.s_addr = inet_addr(argv[1]);  
  80.     else  
  81.     {  
  82.         char ip[128];  
  83.         get_ip("eno16777736", ip);  
  84.         server_addr.sin_addr.s_addr = inet_addr(ip);  
  85.     }  
  86.   
  87.     //建立sockfd  
  88.     if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)  
  89.     {  
  90.         perror("socket");  
  91.         exit(EXIT_FAILURE);  
  92.     }  
  93.       
  94.     //输出ip和port信息,用于测试  
  95.     printf("server_ip = %s\nserver_port = %d\nlisnum = %d\n", inet_ntoa(server_addr.sin_addr), server_port, lisnum);  
  96.   
  97.     //绑定sockfd和服务器的IP地址server_addr  
  98.     if(bind(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)  
  99.     {  
  100.         perror("bind");  
  101.         exit(EXIT_FAILURE);  
  102.     }  
  103.       
  104.     //监听sockfd  
  105.     if(listen(sockfd, lisnum) == -1)  
  106.     {  
  107.         perror("listen");  
  108.         exit(EXIT_FAILURE);  
  109.     }  
  110.   
  111.       
  112.     while(1)  
  113.     {  
  114.         printf("\n---- wait for client connect ---\n");  
  115.   
  116.         //等待接收客户端的连接  
  117.         //连接成功后,客户端地址信息存储在client_addr中  
  118.         //新建立的socket描述符存储在newfd中  
  119.         len = sizeof(struct sockaddr);  
  120.         if((newfd = accept(sockfd, (struct sockaddr *)&client_addr, &len)) == -1)  
  121.         {  
  122.             perror("accept");  
  123.             exit(EXIT_FAILURE);  
  124.         }  
  125.         //打印客户端地址信息 inet_ntoa  ntohs  
  126.         printf("server: got connection from %s, port %d, socket %d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), newfd);  
  127.   
  128.         while(1)  
  129.         {  
  130.             FD_ZERO(&rfds);//初始化rfds为空  
  131.             FD_SET(0, &rfds);//将标准输入的描述符0加入到集合rfds中  
  132.             FD_SET(newfd, &rfds);//将newfd加入到集合rfds中  
  133.             maxfd = newfd + 1;  
  134.             tv.tv_sec = 1;//阻塞等待时间为1s  
  135.             tv.tv_usec = 0;  
  136.               
  137.             retval = select(maxfd, &rfds, NULL, NULL, &tv);//多路复用,同时监测描述符0和newfd              
  138.             if(retval == -1)//select函数执行出错  
  139.             {  
  140.                 perror("select");  
  141.                 exit(EXIT_FAILURE);  
  142.             }  
  143.             else if(retval == 0)//select函数执行超时  
  144.                 continue;  
  145.             else//有描述符引起异常  
  146.             {  
  147.                 if(FD_ISSET(0, &rfds))//判断是不是标准输入0引起的异常  
  148.                 {  
  149.                     bzero(buf, sizeof(buf));//清空buf  
  150.                     fgets(buf, sizeof(buf)-1, stdin);//从终端接收输入  
  151.   
  152.                     if(!strncasecmp(buf, "quit", 4))//判断是否为退出  
  153.                     {  
  154.                         printf("i will close the connect!\n");  
  155.                         break;  
  156.                     }  
  157.                       
  158.                     len = send(newfd, buf, strlen(buf)-1, 0);//向客户端发送消息  
  159.                     if(len > 0)  
  160.                     {  
  161.                         printf ("send successful,%d byte send!\n",len);  
  162.                     }  
  163.                     else  
  164.                     {  
  165.                         printf("message '%s' send failure !\n", buf);  
  166.                         printf("errno code is %d, errno message is '%s'\n", errno, strerror(errno));  
  167.                         break;  
  168.                     }                     
  169.                 }  
  170.                   
  171.                 if(FD_ISSET(newfd, &rfds))//判断是不是newfd引起的异常  
  172.                 {  
  173.                     bzero(buf, sizeof(buf));  
  174.                     len = recv(newfd, buf, sizeof(buf)-1, 0);//从客户端接收消息  
  175.                     if(len > 0 )  
  176.                         printf("message recv successful : '%s', %d Byte recv\n", buf, len);  
  177.                     else if(len < 0)  
  178.                     {  
  179.                         printf("recv failure !\nerrno code is %d, errno message is '%s'\n", errno, strerror(errno));  
  180.                         break;  
  181.                     }  
  182.                     else//如果客户端已关闭  
  183.                     {  
  184.                         printf("the other one close quit\n");  
  185.                         break;  
  186.                     }                     
  187.                 }  
  188.             }         
  189.         }  
  190.         close(newfd);  
  191.         printf("need other connection ? (no -> quit) : ");  
  192.         fflush(stdout);  
  193.         bzero(buf, sizeof(buf));//清空buf  
  194.         fgets(buf, sizeof(buf)-1, stdin);//从终端接收输入  
  195.         if(!strncasecmp(buf, "no", 2))//判断是否继续等待连接  
  196.         {  
  197.             printf("quit!\n");  
  198.             break;  
  199.         }     
  200.     }     
  201.   
  202.     close(sockfd);  
  203.   
  204.     return 0;  
  205. }  
  206.   
  207.   
  208. void get_ip(char * str, char *ip)  
  209. {  
  210.     int inet_sock;  
  211.     struct ifreq ifr;  
  212.     inet_sock = socket(AF_INET, SOCK_DGRAM, 0);  
  213.     strcpy(ifr.ifr_name, str);//#include <net/if.h>  
  214.     if (ioctl(inet_sock, SIOCGIFADDR, &ifr) < 0)//#include <sys/ioctl.h>  
  215.     {  
  216.         perror("ioctl");  
  217.         exit(EXIT_FAILURE);  
  218.     }  
  219.     sprintf(ip,"%s", inet_ntoa(((struct sockaddr_in*)&(ifr.ifr_addr))->sin_addr));  
  220.     close(inet_sock);     
  221. }  

客户端代码

[cpp]  view plain  copy  print ? 在CODE上查看代码片 派生到我的代码片
  1. /************************************************************************* 
  2.     > File Name: socket_select_client.c 
  3.     > Author: genglut 
  4.     > Mail: genglut@163.com 
  5.     > Created Time: 2014年12月22日 星期一 18时06分06秒 
  6.  ************************************************************************/  
  7.   
  8. #include <stdio.h>  
  9. #include <string.h>  
  10. #include <errno.h>  
  11. #include <sys/socket.h>  
  12. #include <resolv.h>  
  13. #include <stdlib.h>  
  14. #include <netinet/in.h>  
  15. #include <arpa/inet.h>  
  16. #include <unistd.h>  
  17.   
  18. #define MAXBUF 1024  
  19.   
  20. int main(int argc, char *argv[])  
  21. {  
  22.     int sockfd;  
  23.     socklen_t len;  
  24.     struct sockaddr_in server_addr;  
  25.     char buf[MAXBUF + 1];  
  26.   
  27.     //下面是select用到的变量的定义  
  28.     fd_set rfds;  
  29.     struct timeval tv;  
  30.     int retval;  
  31.     int maxfd = -1;  
  32.       
  33.     if(argc != 3)  
  34.     {  
  35.         printf("error failure, it must be:\n\t\t%s IP port \n", argv[0]);  
  36.         exit(EXIT_FAILURE);  
  37.     }  
  38.   
  39.     if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)  
  40.     {  
  41.         perror("socket");  
  42.         exit(EXIT_FAILURE);  
  43.     }  
  44.   
  45.     bzero(&server_addr, sizeof(server_addr));  
  46.     server_addr.sin_family = AF_INET;  
  47.     server_addr.sin_port = htons(atoi(argv[2]));  
  48.     server_addr.sin_addr.s_addr = inet_addr(argv[1]);  
  49.   
  50.     if(connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)  
  51.     {  
  52.         perror("connect");  
  53.         exit(EXIT_FAILURE);  
  54.     }  
  55.   
  56.     printf("already connected to server %s\n", argv[1]);  
  57.       
  58.       
  59.     while(1)  
  60.     {  
  61.         FD_ZERO(&rfds);//初始化rfds为空  
  62.         FD_SET(0, &rfds);//将标准输入的描述符0加入到集合rfds中  
  63.         FD_SET(sockfd, &rfds);//将newfd加入到集合rfds中  
  64.         maxfd = sockfd + 1;  
  65.         tv.tv_sec = 1;//阻塞等待时间为1s  
  66.         tv.tv_usec = 0;  
  67.           
  68.         retval = select(maxfd, &rfds, NULL, NULL, &tv);//多路复用,同时监测描述符0和newfd  
  69.           
  70.         if(retval == -1)//select函数执行出错  
  71.         {  
  72.             perror("select");  
  73.             exit(EXIT_FAILURE);  
  74.         }  
  75.         else if(retval == 0)//select函数执行超时  
  76.             continue;  
  77.         else//有描述符引起异常  
  78.         {  
  79.             if(FD_ISSET(0, &rfds))//判断是不是标准输入0引起的异常  
  80.             {  
  81.                 bzero(buf, sizeof(buf));//清空buf  
  82.                 fgets(buf, sizeof(buf)-1, stdin);//从终端接收输入  
  83.   
  84.                 if(!strncasecmp(buf, "quit", 4))//判断是否为退出  
  85.                 {  
  86.                     printf("i will quit!\n");  
  87.                     break;  
  88.                 }  
  89.                   
  90.                 len = send(sockfd, buf, strlen(buf)-1, 0);//向客户端发送消息  
  91.                 if(len > 0)  
  92.                 {  
  93.                     printf ("send successful,%d byte send!\n",len);  
  94.                 }  
  95.                 else  
  96.                 {  
  97.                     printf("message '%s' send failure !\n", buf);  
  98.                     printf("errno code is %d, errno message is '%s'\n", errno, strerror(errno));  
  99.                     break;  
  100.                 }                     
  101.             }  
  102.               
  103.             if(FD_ISSET(sockfd, &rfds))//判断是不是newfd引起的异常  
  104.             {  
  105.                 bzero(buf, sizeof(buf));  
  106.                 len = recv(sockfd, buf, sizeof(buf)-1, 0);//从客户端接收消息  
  107.                 if(len > 0 )  
  108.                     printf("message recv successful : '%s', %d Byte recv\n", buf, len);  
  109.                 else if(len < 0)  
  110.                 {  
  111.                     printf("recv failure !\nerrno code is %d, errno message is '%s'\n", errno, strerror(errno));  
  112.                     break;  
  113.                 }  
  114.                 else//如果客户端已关闭  
  115.                 {  
  116.                     printf("the other one close, quit\n");  
  117.                     break;  
  118.                 }                     
  119.             }  
  120.         }     
  121.     }  
  122.       
  123.     close(sockfd);  
  124.     printf("i quited!\n");  
  125.     return 0;  
  126. }  

原文链接

http://blog.csdn.net/geng823/article/details/42099569

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux网络编程 - TCP Socket 简单练习:select同时监测多个描述符 的相关文章

  • 机器人框架

    ROS Rock Yarp Orocos
  • 列王的纷争-深度传感器已被巨头瓜分?

    origin http mt sohu com 20170325 n484729546 shtml 我们常常说苹果富可敌国 但是你这么说其实是在侮辱苹果 苹果可比美国政府有钱多了 根据最新消息 xff0c 美国政府账上的现金 xff0c 只
  • 不得不看!国内深度摄像头方案大起底

    origin http pieeco baijia baidu com article 517947 引言 xff1a 市场对深度视觉技术需求趋于井喷 xff0c 但可以提供产品和方案的公司寥寥无几 xff0c 本文分析了国内三家各具特点的
  • VR中的9轴传感器(重力加速度/陀螺仪/磁力计)

    origin http blog csdn net dabenxiong666 article details 53836503 前言 传感器的调试过程 xff0c 一般根据原厂提供demo代码 xff0c 调试数据接口 xff0c 将数据
  • STM32中AD采样的三种方法分析

    在进行STM32F中AD采样的学习中 xff0c 我们知道AD采样的方法有多种 xff0c 按照逻辑程序处理有三种方式 xff0c 一种是查询模式 xff0c 一种是中断处理模式 xff0c 一种是DMA模式 三种方法按照处理复杂方法DMA
  • 神经网络:比原来更容易学习了

    origin http geek csdn net news detail 195039 原文 xff1a NEURAL NETWORKS YOU VE GOT IT SO EASY 作者 xff1a Steven Dufresne 翻译
  • NuttX 编译系统

    origin http blog csdn net zhumaill article details 24400441 xff08 嵌入式 实时操作系统 rtos nuttx 7 1 makefile xff09 NuttX 编译系统 转载
  • NuttX 启动流程

    origin http blog csdn net zhumaill article details 23261543 xff08 嵌入式 实时操作系统 rtos nuttx 7 1 stm32 源代码分析 xff09 NuttX 启动流程
  • nuttx操作系统的移植以及下载

    origin http blog csdn net seawolfe article details 70244672 1 在ubuntu根目录下 xff1a root 64 ubuntu apt get update 更新包 2 root
  • 机器人峰会厂商

    origin http www chinarobtop com exhibition exhibition php 埃夫特 清能德创 芜湖瑞思 芜湖哈特 山东帅克机械 宁波慈兴轴承 A6 成都卡诺普 绿的谐波
  • 机器人公司

    1 螺趣科技 2 米兔机器人 3 360
  • 解:高性能MEMS IMU解决方案-ADXRS290

    origin https ezchina analog com message 34890 对于复杂且高动态惯性配置的MEMS IMU应用 xff0c 评估功能时需要考虑许多属性 在设计周期早期评估这些属性优于追逐开放性成果 xff0c 从
  • 关于DIY电池均衡器--被动均衡---蓄电池--电瓶车电池组电压均衡的经历

    提示 xff1a 文章写完后 xff0c 目录可以自动生成 xff0c 如何生成可参考右边的帮助文档 前言 随着电动车长时间的反复使用 xff0c 电池参数难免会发生变化 xff0c 当电池组中各节电池参数不一时 xff0c 便会出现充电时
  • CMakeLists.txt与Makefile 的区别

    我平时一般是在windows使用VS编程 xff0c 但是偶尔在网上查资料的时候也会下载一些别人的代码 xff0c 其中就经常对CMakeLists txt和Makefile文件产生疑惑 xff0c 下面我来分析一下这两个经常使用的地方 C
  • 链接提示 extern "C"

    在 C 43 43 中调用 C 代码时 xff0c 需要给编译器指定 xff23 代码要按照 xff23 语言的编译器编译 xff0c 否则编译器会将 xff23 代码按照默认的C 43 43 编译器来编译 xff23 代码 xff0c 这
  • C/C++实现你的浪漫表白:浪漫流星雨表白程序,

    想要讨女朋友欢心也巩固自己所学的知识 xff0c 各位小伙伴有自己的想法了吗 xff1f 准备好想要怎样实施了吗 xff1f 有什么美好的计划了吗 xff1f 如果没有的话那么别慌 xff0c 我知道 xff0c 在座的各位肯定都是有自己的
  • DDR4原理及硬件设计

    DDR4 DRAM的工作原理 其引脚按照功能可以分为7类 xff1a 前3类为电源 地 配置 后4类为 xff1a 控制信号 时钟信号 地址信号 数据信号 电源 地 配置信号的功能很简单 xff0c 在此不赘述 控制信号主要是用来完成DDR
  • RK3568最小系统四层板设计总结

    很久没有关注DDR4和DDR5相关知识了 xff0c 利用找工作在家休息间隙从网上下载了RK3568的原理图和6层板的PCB参考设计 xff0c 将6层板改为4层板设计 进行总结之前 xff0c 先将设计时关于Allegro设计小技巧进行总
  • 部门管理经验小结

    很久没有针对管理做总结了 xff0c 回武汉后一直做工程师 xff0c 现对管理知识体系进行总结 xff1a 部门管理按照如下框图1所示 图1
  • STM32驱动开发(二)--USB Device RNDIS虚拟网卡(usb hound抓包完整数据流分析)

    一 简介 抓包工具 xff1a usb hound xff0c 本例使用安卓手机作为device 使用RNDIS功能连接电脑虚拟网卡 抓取完整数据流包按流程进行分析 数据流程熟悉之后 xff0c 查看stm32或者其他厂家的USB库开发RN

随机推荐