• 国庆10.01


    TCPselect

    代码

    服务器

    1. #include<myhead.h>
    2. #include<sqlite3.h>
    3. #define PORT 6666 //端口号
    4. #define IP "192.168.0.104" //IP地址
    5. //键盘事件
    6. int jp(fd_set tempfds,int maxfd)
    7. {
    8. char buf[128] = ""; //用来接收数据
    9. char buf1[128] = ""; //用来接收数据
    10. int snfd = -1; //用来接受从终端的文件描述符
    11. bzero(buf,sizeof(buf)); //清空字符串
    12. int res = scanf("%d %s",&snfd,buf); //从终端读取文件描述符和接收数据
    13. while(getchar() != 10); //循环吸收垃圾字符
    14. if(res != 2) //判断是否输入了两个数据
    15. {
    16. printf("输入数据格式错误!\n");
    17. return -1;
    18. }
    19. if(snfd <= 2 || FD_ISSET(snfd,&tempfds) == 0) //判断是否正确输入文件描述符
    20. {
    21. printf("输入非法文件描述符:%d\n",snfd);
    22. return -1;
    23. }
    24. sprintf(buf1,"%c%c%s",'s',':',buf);
    25. if(send(snfd,buf1,sizeof(buf1),0) < 0) //判断是否发送成功
    26. {
    27. ERR_MSG("send");
    28. return -1;
    29. }
    30. return 0;
    31. }
    32. //客户端链接事件
    33. int lj(int sfd,struct sockaddr_in sevecin[1024],fd_set *preadfds,int *maxfd)
    34. {
    35. int newfd = -1;
    36. struct sockaddr_in cin; //客户端信息结构体
    37. socklen_t len = sizeof(cin); //信息结构体真实大小
    38. //连接客户端
    39. newfd = accept(sfd,(struct sockaddr *)&cin,&len);
    40. if(newfd < 0) //判断是否连接成功
    41. {
    42. ERR_MSG("newfd");
    43. return -1;
    44. }
    45. printf("[%s : %d] 客户端连接成功!\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));
    46. sevecin[newfd] = cin; //将新的客户端连接到客户端数组中
    47. FD_SET(newfd,preadfds);//将新的文件描述符添加到读集合中
    48. *maxfd = *maxfd > newfd ? *maxfd : newfd;//更新最大文件描述符
    49. return 0;
    50. }
    51. //客户端交互事件
    52. int jh(int fd, struct sockaddr_in sevecin[1024],fd_set *readfds,int *maxfd)
    53. {
    54. char buf[128] = ""; //搬运工
    55. bzero(buf,sizeof(buf)); //清空字符串
    56. //接收
    57. ssize_t res = recv(fd,buf,sizeof(buf),0);
    58. if(res < 0)
    59. {
    60. ERR_MSG("recv");
    61. return -1;
    62. }
    63. else if(res == 0)
    64. {
    65. printf("[%s : %d]客户端已下线!\n",inet_ntoa(sevecin[fd].sin_addr),ntohs(sevecin[fd].sin_port));
    66. close(fd); //关闭文件描述符
    67. FD_CLR(fd,readfds);//从读集合中删除该信息
    68. while(FD_ISSET(*maxfd,readfds) && (*maxfd)-- >= 0);//更新最大文件描述符
    69. return 0;
    70. }
    71. printf("[%s : %d]: %s\n",inet_ntoa(sevecin[fd].sin_addr),\
    72. ntohs(sevecin[fd].sin_port),buf);
    73. //发送
    74. strcat(buf,"*_*");
    75. if(send(fd,buf,sizeof(buf),0) < 0)
    76. {
    77. ERR_MSG("send");
    78. return -1;
    79. }
    80. return 0;
    81. }
    82. //主函数
    83. int main(int argc, const char *argv[])
    84. {
    85. //创建套接字
    86. int sfd = -1;
    87. if((sfd = socket(AF_INET,SOCK_STREAM,0)) < 0)//判断是否创建成功
    88. {
    89. ERR_MSG("socket");
    90. return -1;
    91. }
    92. //端口快速复用
    93. int reuse = 1;
    94. if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) < 0)
    95. {
    96. ERR_MSG("setsockopt");
    97. return -1;
    98. }
    99. //填充信息结构体
    100. struct sockaddr_in sin;
    101. sin.sin_family = AF_INET;
    102. sin.sin_port = htons(PORT); //端口号
    103. sin.sin_addr.s_addr = inet_addr(IP); //IP
    104. //绑定
    105. if(bind(sfd, (struct sockaddr *)&sin,sizeof(sin)) < 0)//判断是否绑定成功
    106. {
    107. ERR_MSG("bind");
    108. return -1;
    109. }
    110. //监听
    111. if(listen(sfd,128) < 0)//判断是否设置监听成功
    112. {
    113. ERR_MSG("listen");
    114. return -1;
    115. }
    116. //创建一个读集合
    117. fd_set readfds,tempfds;
    118. //清空集合
    119. FD_ZERO(&readfds);
    120. //将需要监测的文件放入到集合中
    121. FD_SET(0,&readfds);
    122. FD_SET(sfd,&readfds);
    123. //记录最大文件描述符
    124. int maxfd = sfd;
    125. //记录select函数的返回值
    126. int s_res;
    127. //备份连接成功的客户端信息
    128. struct sockaddr_in sevecin[1024];
    129. bzero(sevecin,sizeof(sevecin)); //清空数组
    130. while(1)
    131. {
    132. FD_ZERO(&tempfds);
    133. tempfds = readfds;
    134. s_res = select(maxfd+1,&tempfds,NULL,NULL,NULL); //多路复用
    135. if(s_res < 0)
    136. {
    137. ERR_MSG("select");
    138. return -1;
    139. }
    140. if(s_res == 0)
    141. {
    142. printf("超时!\n");
    143. break;
    144. }
    145. for(int i = 0; i <= maxfd; i++)
    146. {
    147. if(FD_ISSET(i,&tempfds) == 0)
    148. {
    149. continue;
    150. }
    151. if(i == 0)
    152. {
    153. //键盘事件
    154. jp(readfds,maxfd);
    155. }
    156. else if(i == sfd)
    157. {
    158. //客户端链接事件
    159. lj(sfd,sevecin,&readfds,&maxfd);
    160. }
    161. else
    162. {
    163. //客户端交互事件
    164. jh(i,sevecin,&readfds,&maxfd);
    165. }
    166. }
    167. }
    168. if(close(sfd) < 0)
    169. {
    170. ERR_MSG("close");
    171. return -1;
    172. }
    173. return 0;
    174. }

    客户端

    1. #include<myhead.h>
    2. #include<sqlite3.h>
    3. #define PORT 6666 //端口号
    4. #define IP "192.168.0.104" //IP
    5. int main(int argc, const char *argv[])
    6. {
    7. //创建流式套接字
    8. int cfd = socket(AF_INET,SOCK_STREAM,0);
    9. if(cfd < 0) //判断是否创建成功
    10. {
    11. ERR_MSG("socket");
    12. }
    13. //填充客户端地址信息
    14. struct sockaddr_in cin;
    15. cin.sin_family = AF_INET;
    16. cin.sin_port = htons(PORT); //端口
    17. cin.sin_addr.s_addr = inet_addr(IP); //IP
    18. //连接
    19. if(connect(cfd,(struct sockaddr *)&cin,sizeof(cin)) < 0)
    20. {
    21. ERR_MSG("connect");
    22. return -1;
    23. }
    24. //定义读集合
    25. fd_set readfds,tempfds;
    26. FD_ZERO(&readfds); //清空集合
    27. FD_SET(0,&readfds); //加入集合
    28. FD_SET(cfd,&readfds);
    29. char buf[128] = ""; //定义搬运工
    30. while(1)
    31. {
    32. tempfds = readfds;
    33. bzero(buf,sizeof(buf));
    34. //多路复用
    35. int s_res = select(cfd+1,&tempfds,NULL,NULL,NULL);
    36. if(s_res < 0)
    37. {
    38. ERR_MSG("select");
    39. return -1;
    40. }
    41. if(s_res == 0)
    42. {
    43. printf("超时!\n");
    44. break;
    45. }
    46. //向服务器发送数据
    47. if(FD_ISSET(0,&tempfds))
    48. {
    49. bzero(buf,sizeof(buf));//清空字符串
    50. fgets(buf,sizeof(buf),stdin); //从终端获取数据
    51. buf[strlen(buf) - 1] = 0; //换行变成'\0'
    52. if(send(cfd,buf,sizeof(buf),0) < 0) //发送数据并判断数据是否发送成功
    53. {
    54. ERR_MSG("send");
    55. return -1;
    56. }
    57. }
    58. //从服务器接受数据
    59. if(FD_ISSET(cfd,&tempfds))
    60. {
    61. bzero(buf,sizeof(buf)); //清空字符串
    62. int res = recv(cfd,buf,sizeof(buf),0);
    63. if(res < 0) //判断是否成功接受
    64. {
    65. ERR_MSG("recv");
    66. return -1;
    67. }
    68. else if(res == 0) //判断服务器是否下线
    69. {
    70. printf("服务器下线!\n");
    71. break;
    72. }
    73. printf("%s\n",buf);
    74. fflush(stdout);
    75. }
    76. }
    77. if(close(cfd)) //关闭文件描述符并判断是否关闭成功
    78. {
    79. ERR_MSG("close");
    80. return -1;
    81. }
    82. return 0;
    83. }

    现象

  • 相关阅读:
    android Seekbar当点击的时候有一个圆圈
    算法与数据结构【30天】集训营——图的遍历之深度优先搜索、广度优先搜索(28)
    基于SpringBoot的健身房会员管理系统设计与实现(源码+lw+部署文档+讲解等)
    MySQL数据库设计需要注意的点
    踩坑ImageMagick将ios图片文件HEIC格式转jpg/png等
    理解Nginx反向代理详解
    使用代理绕过网站的反爬机制
    百花齐放的国产数据库,献礼国庆节
    【组合导航】基于matlab卡尔曼滤波残差的组合导航系统故障诊断【含Matlab源码 4002期】
    Java刷题面试系列习题(一)
  • 原文地址:https://blog.csdn.net/weixin_52238362/article/details/133468863