1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <process.h>
4 #include <winsock2.h>
5 #include <windows.h>
6
7 #define BUF_SIZE 1024
8 #define READ 3
9 #define WRITE 5
10
11 typedef struct //socket info
12 {
13 SOCKET hClntSock;
14 SOCKADDR_IN clntAdr;
15 }PER_HANDLE_DATA, *LPPER_HANDLE_DATA;
16
17 typedef struct //buffer info
18 {
19 OVERLAPPED overlapped;
20 WSABUF wsaBuf;
21 char buffer[BUF_SIZE];
22 int rwMode; // READ or WRITE
23 }PER_IO_DATA, *LPPER_IO_DATA;
24
25 unsigned WINAPI EchoThreadMain(LPVOID CompletionPortIO);
26 void ErrorHanding(char *msg);
27
28 int main(int argc, char *argv[])
29 {
30 WSADATA wsaData;
31 HANDLE hComPort;
32 SYSTEM_INFO sysInfo;
33 LPPER_IO_DATA ioInfo;
34 LPPER_HANDLE_DATA handleInfo;
35
36 SOCKET hServSock;
37 SOCKADDR_IN servAdr;
38 int recvBytes, i, flags = 0;
39 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
40 ErrorHanding("WSAStartUp() error!");
41
42 hComPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
43 GetSystemInfo(&sysInfo);
44 for (i = 0; i < sysInfo.dwNumberOfProcessors; i++)
45 _beginthreadex(NULL, 0, EchoThreadMain, (LPVOID)hComPort, 0, NULL);
46
47 hServSock = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
48 memset(&servAdr, 0, sizeof(servAdr));
49 servAdr.sin_family = AF_INET;
50 servAdr.sin_addr.s_addr = htonl(INADDR_ANY);
51 servAdr.sin_port = htons(atoi(argv[1]));
52
53 bind(hServSock, (SOCKADDR *)&servAdr, sizeof(servAdr));
54 listen(hServSock, 5);
55
56 while (1)
57 {
58 SOCKET hClntSock;
59 SOCKADDR_IN clntAdr;
60 int addrLen = sizeof(clntAdr);
61
62 hClntSock = accept(hServSock, (SOCKADDR *)&servAdr, &addrLen);
63 handleInfo = (LPPER_HANDLE_DATA)malloc(sizeof(PER_HANDLE_DATA));
64 handleInfo->hClntSock = hClntSock;
65 memcpy(&(handleInfo->clntAdr), &clntAdr, addrLen);
66
67 CreateIoCompletionPort((HANDLE)hClntSock, hComPort, (DWORD)handleInfo, 0);
68
69 ioInfo = (LPPER_IO_DATA)malloc(sizeof(PER_IO_DATA));
70 memset(&(ioInfo->overlapped), 0, sizeof(OVERLAPPED));
71 ioInfo->wsaBuf.len = BUF_SIZE;
72 ioInfo->wsaBuf.buf = ioInfo->buffer;
73 ioInfo->rwMode = READ;
74 WSARecv(handleInfo->hClntSock, &(ioInfo->wsaBuf), 1, (LPDWORD)&recvBytes, (LPDWORD)&flags, &(ioInfo->overlapped), NULL);
75 }
76 return 0;
77 } // end of main function
78
79 unsigned WINAPI EchoThreadMain(LPVOID pComPort)
80 {
81 HANDLE hComPort = (HANDLE)pComPort;
82 SOCKET sock;
83 DWORD bytesTrans;
84 LPPER_HANDLE_DATA handleInfo;
85 LPPER_IO_DATA ioInfo;
86 DWORD flags = 0;
87
88 while (1)
89 {
90 GetQueuedCompletionStatus(hComPort, &bytesTrans, (LPDWORD) &handleInfo, (LPOVERLAPPED *) &ioInfo, INFINITE);
91 sock = handleInfo->hClntSock;
92
93 if (ioInfo->rwMode == READ)
94 {
95 puts("message received!");
96 if (bytesTrans == 0)
97 {
98 closesocket(sock);
99 free(handleInfo);
100 free(ioInfo);
101 continue;
102 }
103
104 memset(&(ioInfo->overlapped), 0, sizeof(OVERLAPPED));
105 ioInfo->wsaBuf.len = bytesTrans;
106 ioInfo->rwMode = WRITE;
107 WSASend(sock, &(ioInfo->wsaBuf), 1, NULL, 0, &(ioInfo->overlapped), NULL);
108
109 ioInfo = (LPPER_IO_DATA)malloc(sizeof(PER_IO_DATA));
110 memset(&(ioInfo->overlapped), 0, sizeof(OVERLAPPED));
111 ioInfo->wsaBuf.len = BUF_SIZE;
112 ioInfo->wsaBuf.buf = ioInfo->buffer;
113 ioInfo->rwMode = READ;
114 WSARecv(sock, &(ioInfo->wsaBuf), 1, NULL, &flags, &(ioInfo->overlapped), NULL);
115 }
116 else
117 {
118 puts("message sent!");
119 free(ioInfo);
120 }
121 }
122 return 0;
123 }
124
125 void ErrorHanding(char *msg)
126 {
127 fputs(msg, stderr);
128 fputc('\n', stderr);
129 exit(1);
130 }