1. #include <stdio.h>
    2. #include <sys/types.h>
    3. #include <sys/socket.h>
    4. #include <netdb.h>
    5. #include <stdlib.h>
    6. #include <unistd.h>
    7. #include <arpa/inet.h>
    8. #include <netinet/in.h>
    9. #include <errno.h>
    10. #include <string.h>
    11. #include <ctype.h>
    12. #include <sys/select.h>
    13. int main()
    14. {
    15. // 创建监听套接字
    16. int lfd = socket(AF_INET, SOCK_STREAM, 0);
    17. if (lfd == -1)
    18. {
    19. perror("socket error");
    20. exit(1);
    21. }
    22. // 设置端口复用
    23. int opt = 1;
    24. setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(opt));
    25. //IP地址与端口号信息
    26. struct sockaddr_in serv_addr;
    27. memset(&serv_addr, 0, sizeof(serv_addr));
    28. serv_addr.sin_family = AF_INET;
    29. serv_addr.sin_port = htons(9317);
    30. serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    31. // 绑定、监听
    32. int ret = bind(lfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
    33. if (ret == -1)
    34. {
    35. perror("bind error");
    36. exit(1);
    37. }
    38. ret = listen(lfd, 64);
    39. if (ret == -1)
    40. {
    41. perror("listen error");
    42. exit(1);
    43. }
    44. // 用来接收客户端ip信息
    45. struct sockaddr_in client_addr;
    46. socklen_t cli_addr_len = sizeof(struct sockaddr_in);
    47. // select用的两个事件数组
    48. fd_set reads, temps;
    49. // 最大的事件fd
    50. int max_fd;
    51. // 初始化reads事件表
    52. FD_ZERO(&reads);
    53. // 设置内核监视监听套接字
    54. FD_SET(lfd, &reads);
    55. max_fd = lfd;
    56. while (1)
    57. {
    58. // 复制reads表传参,保留原reads表不变,因为select会修改传进去的表
    59. temps = reads;
    60. int ret = select(max_fd + 1, &temps, NULL, NULL, NULL);
    61. if (ret < 0)
    62. {
    63. fprintf(stderr, "select error: %s\n", strerror(errno));
    64. exit(1);
    65. }
    66. // 监听套接字有事件
    67. if (FD_ISSET(lfd, &temps))
    68. {
    69. int cfd;
    70. if ((cfd = accept(lfd, (struct sockaddr *)&client_addr, &cli_addr_len)) < 0)
    71. {
    72. fprintf(stderr, "accept error: %s\n", strerror(errno));
    73. exit(1);
    74. }
    75. // 新套接字(客户套接字)加入reads表
    76. FD_SET(cfd, &reads);
    77. max_fd = max_fd > cfd ? max_fd : cfd;
    78. }
    79. int k;
    80. for (k = lfd + 1; k <= max_fd; k++)
    81. {
    82. // 客户端有事件,处理
    83. if (FD_ISSET(k, &temps))
    84. {
    85. char buff[1024];
    86. int rec_len, i;
    87. if ((rec_len = recv(k, buff, sizeof(buff), 0)) < 0)
    88. {
    89. fprintf(stderr, "read error: %s\n", strerror(errno));
    90. exit(1);
    91. }
    92. else if (rec_len == 0)
    93. {
    94. // 客户端关闭连接
    95. close(k);
    96. FD_CLR(k, &reads);
    97. }
    98. else
    99. {
    100. for (i = 0; i < rec_len; ++i)
    101. {
    102. buff[i] = toupper(buff[i]);
    103. }
    104. send(k, buff, rec_len, 0);
    105. }
    106. }
    107. }
    108. }
    109. close(lfd);
    110. return 0;
    111. }