select:
首先设置一个lfd绑定服务端地址结构,用于监听新的连接。select函数调用,用于对整个fd数组进行监听,该数组最大限制1024,通过遍历,来确定是哪个fd有变化:
1.如果是lfd:那么可能是新的连接进来,就要调用accept阻塞监听获得这个新的连接,将fd加入到数组中;
2.其他fd,有可能是需要断开连接,也有可能是要有数据传输。
1.#include <stdio.h>
2.#include <stdlib.h>
3.#include <unistd.h>
4.#include <string.h>
5.#include <arpa/inet.h>
6.#include <ctype.h>
7.
8.#include "wrap.h"
9.
10.#define SERV_PORT 6666
11.
12.int main(int argc, char *argv[])
13.{
14. int i, j, n, nready;
15.
16. int maxfd = 0;
17.
18. int listenfd, connfd;
19.
20. char buf[BUFSIZ]; /* #define INET_ADDRSTRLEN 16 */
21.
22. struct sockaddr_in clie_addr, serv_addr;
23. socklen_t clie_addr_len;
24.
25. listenfd = Socket(AF_INET, SOCK_STREAM, 0);
26. int opt = 1;
27. setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
28. bzero(&serv_addr, sizeof(serv_addr));
29. serv_addr.sin_family= AF_INET;
30. serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
31. serv_addr.sin_port= htons(SERV_PORT);
32. Bind(listenfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
33. Listen(listenfd, 128);
34.
35.
36. fd_set rset, allset; /* rset 读事件文件描述符集合 allset用来暂存 */
37.
38. maxfd = listenfd;
39.
40. FD_ZERO(&allset);
41. FD_SET(listenfd, &allset); /* 构造select监控文件描述符集 */
42.
43. while (1) {
44. rset = allset; /* 每次循环时都从新设置select监控信号集 */
45. nready = select(maxfd+1, &rset, NULL, NULL, NULL);
46. if (nready < 0)
47. perr_exit("select error");
48.
49. if (FD_ISSET(listenfd, &rset)) { /* 说明有新的客户端链接请求 */
50.
51. clie_addr_len = sizeof(clie_addr);
52. connfd = Accept(listenfd, (struct sockaddr *)&clie_addr, &clie_addr_len); /* Accept 不会阻塞,因为已经知道要有连接了,所以直接连接 */
53.
54. FD_SET(connfd, &allset); /* 向监控文件描述符集合allset添加新的文件描述符connfd */
55.
56. if (maxfd < connfd)
57. maxfd = connfd;
58.
59. if (0 == --nready) /* 只有listenfd有事件, 后续的 for 不需执行 */
60. continue;
61. }
62.
63. for (i = listenfd+1; i <= maxfd; i++) { /* 检测哪个clients 有数据就绪 */
64.
65. if (FD_ISSET(i, &rset)) {
66.
67. if ((n = Read(i, buf, sizeof(buf))) == 0) { /* 当client关闭链接时,服务器端也关闭对应链接 */
68. Close(i);
69. FD_CLR(i, &allset); /* 解除select对此文件描述符的监控 */
70.
71. } else if (n > 0) {
72.
73. for (j = 0; j < n; j++)
74. buf[j] = toupper(buf[j]);
75. Write(i, buf, n);
76. }
77. }
78. }
79. }
80.
81. Close(listenfd);
82.
83. return 0;