标签:set man stdout wait 有一个 异步通知 eof nec 函数
1. 利用异步io通知模型实现回声服务器端
1 #include 2 #include string.h>
3 #include 4
5 #define BUF_SIZE 100
6
7 void CompressSockets(SOCKET hSockArr[], int idx, int total);
8 void CompressEvents(WSAEVENT hEventArr[], int idx, int total);
9 void ErrorHandling(char *msg);
10
11 int main(int argc, char *argv[])
12 {
13 WSADATA wsaData;
14 SOCKET hServSock, hClntSock;
15 SOCKADDR_IN servAdr, clntAdr;
16
17 SOCKET hSockArr[WSA_MAXIMUM_WAIT_EVENTS];
18 WSAEVENT hEventArr[WSA_MAXIMUM_WAIT_EVENTS];
19 WSAEVENT newEvent;
20 WSANETWORKEVENTS netEvents; //保存发生的事件类型信息和错误信息的结构体变量
21
22 int numOfClntSock=0;
23 int strLen, i;
24 int posInfo, startIdx;
25 int clntAdrLen;
26 char msg[BUF_SIZE];
27
28 if(argc!=2) {
29 printf("Usage: %s \n", argv[0]);
30 exit(1);
31 }
32 if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
33 ErrorHandling("WSAStartup() error!");
34
35 hServSock=socket(PF_INET, SOCK_STREAM, 0);
36 memset(&servAdr, 0, sizeof(servAdr));
37 servAdr.sin_family=AF_INET;
38 servAdr.sin_addr.s_addr=htonl(INADDR_ANY);
39 servAdr.sin_port=htons(atoi(argv[1]));
40
41 if(bind(hServSock, (SOCKADDR*) &servAdr, sizeof(servAdr))==SOCKET_ERROR)
42 ErrorHandling("bind() error");
43
44 if(listen(hServSock, 5)==SOCKET_ERROR)
45 ErrorHandling("listen() error");
46
47 newEvent=WSACreateEvent(); //创建manual_reset模式non-signaled状态的事件对象
48 /* 指定hServSock套接字句柄为newEvent的监视对象,希望监视的事件类型为: 有新的连接请求 */
49 if(WSAEventSelect(hServSock, newEvent, FD_ACCEPT)==SOCKET_ERROR)
50 ErrorHandling("WSAEventSelect() error");
51
52 hSockArr[numOfClntSock]=hServSock;
53 hEventArr[numOfClntSock]=newEvent;
54 numOfClntSock++;
55
56 while(1)
57 {
58 /* 验证是否发生事件,成功时返回发生事件的对象信息,只要有一个事件对象的状态变为signaled时就返回
59 * 可通过以宏的方式申明的WSA_MAXIMUN_WAIT_EVENTS常量得知WSAWaitMulltipleEvents函数可以同时监听的最大事件对象数,该常量为64
60 * 通过该函数可以得到转为signaled状态的事件对象中的第一个(按数组中的保存顺序)索引值, 返回值减去常量WSA_WAIT_EVENT_0,可以得到
61 * 转变为signaled状态的事件对象句柄
62 */
63 posInfo=WSAWaitForMultipleEvents(
64 numOfClntSock, hEventArr, FALSE, WSA_INFINITE, FALSE);
65 startIdx=posInfo-WSA_WAIT_EVENT_0;
66 /* 获取所有signaled状态的事件对象 */
67 for(i=startIdx; i)
68 {
69 int sigEventIdx=
70 WSAWaitForMultipleEvents(1, &hEventArr[i], TRUE, 0, FALSE);
71 if((sigEventIdx==WSA_WAIT_FAILED || sigEventIdx==WSA_WAIT_TIMEOUT))
72 {
73 continue;
74 }
75 else
76 { /* 确定与hSockArr[sigEventIdx]套接字句柄相连接的事件对象hEventArr[sigEventIdx]转变为signaled状态的原因,
77 * 发生的事件类型信息和错误信息保存在netEvents结构体变量中
78 */
79 sigEventIdx=i;
80 WSAEnumNetworkEvents(
81 hSockArr[sigEventIdx], hEventArr[sigEventIdx], &netEvents);
82 if(netEvents.lNetworkEvents & FD_ACCEPT)
83 { /* 发生连接请求事件 */
84 if(netEvents.iErrorCode[FD_ACCEPT_BIT]!=0)
85 {
86 puts("Accept Error");
87 break;
88 }
89 /* 接受连接请求 */
90 clntAdrLen=sizeof(clntAdr);
91 hClntSock=accept(
92 hSockArr[sigEventIdx], (SOCKADDR*)&clntAdr, &clntAdrLen);
93 /* 指定hClntSock套接字句柄为newEvent的监视对象,希望监视的事件类型为: 有需要接收的数据和断开连接请求 */
94 newEvent=WSACreateEvent();
95 WSAEventSelect(hClntSock, newEvent, FD_READ|FD_CLOSE);
96
97 hEventArr[numOfClntSock]=newEvent;
98 hSockArr[numOfClntSock]=hClntSock;
99 numOfClntSock++;
100 puts("connected new client...");
101 }
102
103 if(netEvents.lNetworkEvents & FD_READ)
104 { /* 发生有需要接收的数据事件 */
105 if(netEvents.iErrorCode[FD_READ_BIT]!=0)
106 {
107 puts("Read Error");
108 break;
109 }
110 strLen=recv(hSockArr[sigEventIdx], msg, sizeof(msg), 0);
111 send(hSockArr[sigEventIdx], msg, strLen, 0);
112 }
113
114 if(netEvents.lNetworkEvents & FD_CLOSE)
115 {
116 if(netEvents.iErrorCode[FD_CLOSE_BIT]!=0)
117 {
118 puts("Close Error");
119 break;
120 }
121 WSACloseEvent(hEventArr[sigEventIdx]);
122 closesocket(hSockArr[sigEventIdx]);
123
124 numOfClntSock--;
125 CompressSockets(hSockArr, sigEventIdx, numOfClntSock);
126 CompressEvents(hEventArr, sigEventIdx, numOfClntSock);
127 }
128 }
129 }
130 }
131 WSACleanup();
132 return 0;
133 }
134
135 void CompressSockets(SOCKET hSockArr[], int idx, int total)
136 {
137 int i;
138 for(i=idx; i)
139 hSockArr[i]=hSockArr[i+1];
140 }
141 void CompressEvents(WSAEVENT hEventArr[], int idx, int total)
142 {
143 int i;
144 for(i=idx; i)
145 hEventArr[i]=hEventArr[i+1];
146 }
147 void ErrorHandling(char *msg)
148 {
149 fputs(msg, stderr);
150 fputc(‘\n‘, stderr);
151 exit(1);
152 }
2.回声客户端实现
1 #include 2 #include 3 #include string.h>
4 #include 5
6 #define BUF_SIZE 1024
7 void ErrorHandling(char *message);
8
9 int main(int argc, char *argv[])
10 {
11 WSADATA wsaData;
12 SOCKET hSocket;
13 char message[BUF_SIZE];
14 int strLen;
15 SOCKADDR_IN servAdr;
16
17 if(argc!=3) {
18 printf("Usage : %s \n", argv[0]);
19 exit(1);
20 }
21
22 if(WSAStartup(MAKEWORD(2, 2), &wsaData)!=0)
23 ErrorHandling("WSAStartup() error!");
24
25 hSocket=socket(PF_INET, SOCK_STREAM, 0);
26 if(hSocket==INVALID_SOCKET)
27 ErrorHandling("socket() error");
28
29 memset(&servAdr, 0, sizeof(servAdr));
30 servAdr.sin_family=AF_INET;
31 servAdr.sin_addr.s_addr=inet_addr(argv[1]);
32 servAdr.sin_port=htons(atoi(argv[2]));
33
34 if(connect(hSocket, (SOCKADDR*)&servAdr, sizeof(servAdr))==SOCKET_ERROR)
35 ErrorHandling("connect() error!");
36 else
37 puts("Connected...........");
38
39 while(1)
40 {
41 fputs("Input message(Q to quit): ", stdout);
42 fgets(message, BUF_SIZE, stdin);
43
44 if(!strcmp(message,"q\n") || !strcmp(message,"Q\n"))
45 break;
46
47 send(hSocket, message, strlen(message), 0);
48 strLen=recv(hSocket, message, BUF_SIZE-1, 0);
49 message[strLen]=0;
50 printf("Message from server: %s", message);
51 }
52
53 closesocket(hSocket);
54 WSACleanup();
55 return 0;
56 }
57
58 void ErrorHandling(char *message)
59 {
60 fputs(message, stderr);
61 fputc(‘\n‘, stderr);
62 exit(1);
63 }
windows下基于异步通知IO模型的回声服务器和客户端的实现
标签:set man stdout wait 有一个 异步通知 eof nec 函数
原文地址:https://www.cnblogs.com/chenweilin/p/12866397.html