• 国庆day2---select实现服务器并发


    select.c:

    1. #include <myhead.h>
    2. #define ERR_MSG(msg) do{\
    3. fprintf(stderr,"__%d__:",__LINE__);\
    4. perror(msg);\
    5. }while(0)
    6. #define IP "192.168.1.3"
    7. #define PORT 8888
    8. int main(int argc, const char *argv[])
    9. {
    10. //创建报式套接字socket
    11. int sfd=socket(AF_INET,SOCK_STREAM,0);
    12. if(-1==sfd){
    13. ERR_MSG("socket error");
    14. return -1;
    15. }
    16. printf("socket success\n");
    17. //允许端口快速复用setsockopt
    18. int reuse=1;
    19. if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))){
    20. ERR_MSG("setsockopt error");
    21. return -1;
    22. }
    23. //定义一个地址结构体
    24. struct sockaddr_in sin;
    25. sin.sin_family = AF_INET;
    26. sin.sin_port = htons(PORT);
    27. sin.sin_addr.s_addr = inet_addr(IP);
    28. //将套接字和IP、端口绑定bind
    29. if(-1==bind(sfd,(struct sockaddr*)&sin,sizeof(sin))){
    30. ERR_MSG("bind error");
    31. return -1;
    32. }
    33. printf("bind success\n");
    34. //将套接字设置成被动监听状态
    35. if(-1==listen(sfd,128)){
    36. ERR_MSG("listen error");
    37. return -1;
    38. }
    39. int newfd=-1;
    40. fd_set readfds,tempfds;
    41. FD_ZERO(&readfds);
    42. FD_ZERO(&tempfds);
    43. FD_SET(0,&readfds);
    44. FD_SET(sfd,&readfds);
    45. int maxfd=sfd;
    46. struct sockaddr_in saveCin[1024];
    47. int s_res=0;
    48. ssize_t res=0;
    49. char buf[128]="";
    50. struct sockaddr_in cin;
    51. socklen_t addrlen=sizeof(cin);
    52. while(1){
    53. tempfds=readfds;
    54. s_res=select(maxfd+1,&tempfds,NULL,NULL,NULL);
    55. if(-1==s_res){
    56. ERR_MSG("select error");
    57. return -1;
    58. }
    59. else if(0==s_res){
    60. printf("time out...\n");
    61. return -1;
    62. }
    63. for(int i=0;i<=maxfd;i++){
    64. if(!FD_ISSET(i,&tempfds)){
    65. continue;
    66. }
    67. if(0==i){
    68. printf("触发键盘输入事件>>>\n");
    69. bzero(buf,sizeof(buf));
    70. fgets(buf,sizeof(buf),stdin);
    71. buf[strlen(buf)-1]=0;
    72. printf(":%s\n",buf);
    73. }
    74. else if(sfd==i){
    75. printf("触发客户端连接事件>>>\n");
    76. if((newfd=accept(sfd,(struct sockaddr*)&cin,&addrlen)) == -1){
    77. ERR_MSG("accept");
    78. return -1;
    79. }
    80. printf("[%s:%d] newfd=%d 连接成功\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd);
    81. saveCin[newfd]=cin;
    82. FD_SET(newfd,&readfds);
    83. maxfd = maxfd>newfd ? maxfd : newfd;
    84. }
    85. else{
    86. printf("触发客户端交互事件>>>\n");
    87. bzero(buf,sizeof(buf));
    88. res = recv(i,buf,sizeof(buf),0);
    89. if(-1 == res){
    90. ERR_MSG("recv");
    91. return -1;
    92. }
    93. else if(0 == res){
    94. printf("[%s:%d] newfd=%d 下线了\n",inet_ntoa(saveCin[i].sin_addr),ntohs(saveCin[i].sin_port),i);
    95. close(i);
    96. FD_CLR(i,&readfds);
    97. while(FD_ISSET(maxfd,&readfds) == 0 && maxfd-->=0);
    98. continue;
    99. }
    100. printf("[%s:%d] newfd=%d : %s\n",inet_ntoa(saveCin[i].sin_addr),ntohs(saveCin[i].sin_port),i,buf);
    101. strcat(buf,"*-*");
    102. if(send(i,buf,sizeof(buf),0) == -1){
    103. ERR_MSG("send");
    104. return -1;
    105. }
    106. printf("发送成功\n");
    107. }
    108. }
    109. }
    110. close(sfd);
    111. return 0;
    112. }

    效果图: 

  • 相关阅读:
    盘点华为云GaussDB(for Redis)六大秒级能力
    使用Docker安装部署ElasticSearch和ElasticSearch-Head
    二分查找实例3(寻找旋转排序数组中的最小值)
    全栈自动化测试之python的基本数据类型/散列类型
    QT--多线程与MySQL数据库
    Python + Django4 搭建个人博客(十四):实现用户登录和登出功能
    计算机网络 --- TCP与UDP协议
    Vue页面快速使用阿里巴巴矢量图标库
    消息中间件篇之Kafka-高性能设计
    2023年8月知识复习
  • 原文地址:https://blog.csdn.net/qq_53268516/article/details/133465415