单进程单线程IOCP的实现(含客户端和服务端)
server.cpp
1 // TestIOCPone.cpp : This file contains the 'main' function. Program execution begins and ends there. 2 // 3 #define _WINSOCK_DEPRECATED_NO_WARNINGS 4 5 #include <iostream> 6 #include <winsock2.h> 7 #include <process.h> 8 #include <MSWSock.h> 9 #include <assert.h> 10 #include <vector> 11 12 #pragma comment(lib ,"ws2_32.lib") 13 14 HANDLE hIocp = 0; 15 LPFN_ACCEPTEX accept_ex; 16 17 SOCKET listen_socket; 18 19 20 21 22 enum CPK_TYPE { 23 ACCEPT_POST = 1000, //接收请求的完成标识 24 RECV_POST, 25 SEND_POST, 26 CLOSE_POST, 27 }; 28 29 30 class io_context : public OVERLAPPED 31 { 32 public: 33 io_context() { 34 memset(static_cast<OVERLAPPED *>(this), 0, sizeof(OVERLAPPED)); 35 client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 36 buf_ = new char[4096]; 37 w_buf_.buf = buf_; 38 w_buf_.len = 4096; 39 } 40 virtual ~io_context() { 41 42 } 43 44 int op_code = 0; 45 WSABUF w_buf_; 46 char* buf_; 47 SOCKET client_socket; 48 }; 49 50 51 52 53 void init_func(int s) { 54 GUID guidAcceptEx = WSAID_ACCEPTEX; 55 DWORD bytes = 0; 56 if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &guidAcceptEx, 57 sizeof(GUID), &accept_ex, sizeof(LPFN_ACCEPTEX), &bytes, NULL, 58 NULL) == SOCKET_ERROR) 59 { 60 throw std::exception("get acceptex error:", GetLastError()); 61 } 62 } 63 64 65 66 void post_accept() 67 { 68 69 70 io_context* pIoContent = new io_context; 71 72 pIoContent->op_code = ACCEPT_POST; 73 74 DWORD len = 0; 75 76 if (!accept_ex(listen_socket, pIoContent->client_socket, pIoContent->buf_, 0, 77 sizeof(sockaddr_in) + 16, sizeof(sockaddr_in) + 16, &len, 78 pIoContent)) { 79 if (WSA_IO_PENDING != WSAGetLastError()) 80 { 81 throw std::exception("accept_ex error:", GetLastError()); 82 } 83 } 84 } 85 86 void post_recv(io_context* p_io_content) 87 { 88 DWORD recv_len = 0; 89 DWORD flags = 0; 90 p_io_content->op_code = RECV_POST; 91 92 if (WSARecv(p_io_content->client_socket, &p_io_content->w_buf_, 93 1, &recv_len, &flags, p_io_content, NULL) == SOCKET_ERROR) { 94 if (WSAGetLastError() != WSA_IO_PENDING) 95 { 96 throw std::exception("recv error:", GetLastError()); 97 } 98 } 99 } 100 101 void post_send(io_context* p_io_content, const char* data, int len) 102 { 103 DWORD send_len = 0; 104 DWORD flags = 0; 105 106 p_io_content->op_code = SEND_POST; 107 memcpy(p_io_content->w_buf_.buf, data, len); 108 109 p_io_content->w_buf_.len = len; 110 111 if (WSASend(p_io_content->client_socket, &p_io_content->w_buf_, 112 1, &send_len, flags, p_io_content, 113 NULL) == SOCKET_ERROR) { 114 if (WSAGetLastError() != WSA_IO_PENDING) 115 { 116 throw std::exception("send error:", GetLastError()); 117 } 118 } 119 } 120 121 void do_something() 122 { 123 //做其他事情 124 } 125 126 unsigned int __stdcall work_thread(void* lParam) 127 { 128 LPOVERLAPPED overlapped = NULL; 129 ULONG_PTR cl_key = 0; 130 DWORD recv_bytes = 0; 131 while (true) { 132 do_something(); 133 134 BOOL ret = GetQueuedCompletionStatus(hIocp, &recv_bytes, &cl_key, 135 &overlapped, 0); 136 137 138 139 if (ret) { 140 if (CLOSE_POST == cl_key) { 141 std::cout << "close & break " << std::endl; 142 break; 143 } 144 145 std::cout << "recv_bytes=" << recv_bytes << std::endl; 146 io_context* p_io_content = (io_context*)overlapped; 147 148 if (p_io_content->op_code == SEND_POST) { 149 std::cout << "send data ok" << std::endl; 150 PostQueuedCompletionStatus(hIocp, 0, CLOSE_POST, 0); 151 } 152 153 if (p_io_content->op_code == RECV_POST) { 154 std::cout << p_io_content->buf_ << std::endl; 155 156 157 const char* data = "hello from server........"; 158 post_send(p_io_content, data, strlen(data)); 159 160 161 } 162 163 if (ACCEPT_POST == cl_key) { 164 std::cout << "1" << std::endl; 165 post_accept(); 166 167 if (!CreateIoCompletionPort((HANDLE)p_io_content->client_socket, hIocp, NULL, 168 1)) { 169 throw std::exception("bind listen to iocp", GetLastError()); 170 } 171 172 post_recv(p_io_content); 173 } 174 175 176 177 } 178 else 179 { 180 Sleep(1); 181 } 182 } 183 184 return 0; 185 } 186 187 int main() 188 { 189 WSADATA wsa; 190 WSAStartup(MAKEWORD(2, 2), &wsa); 191 192 listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 193 194 assert(listen_socket != INVALID_SOCKET); 195 sockaddr_in addr = { 0 }; 196 addr.sin_family = AF_INET; 197 addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 198 addr.sin_port = htons(12345); 199 200 if (0 != bind(listen_socket, (struct sockaddr *)&addr, sizeof(sockaddr))) { 201 throw std::exception("bind error", GetLastError()); 202 } 203 int work_thread_num_ = 1; 204 hIocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 205 work_thread_num_); 206 if (!hIocp) { 207 throw std::exception("create iocp error", GetLastError()); 208 } 209 init_func(listen_socket); 210 listen(listen_socket, 0); 211 212 213 post_accept(); 214 215 if (!CreateIoCompletionPort((HANDLE)listen_socket, hIocp, ACCEPT_POST, work_thread_num_)) { 216 throw std::exception("bind listen to iocp", GetLastError()); 217 } 218 219 work_thread(NULL); 220 221 222 WSACleanup(); 223 224 } 225 226
client.cpp
1 #define _WINSOCK_DEPRECATED_NO_WARNINGS 2 3 #include <iostream> 4 #include <winsock2.h> 5 6 #pragma comment(lib ,"ws2_32.lib") 7 8 int main() 9 { 10 WSADATA wsa; 11 WSAStartup(MAKEWORD(2, 2), &wsa); 12 13 sockaddr_in client_addr; 14 client_addr.sin_family = AF_INET; 15 client_addr.sin_port = htons(12345); 16 client_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); 17 18 SOCKET client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 19 20 if (0 == connect(client_socket, (const sockaddr*)&client_addr, sizeof(client_addr))) { 21 const char* pbuf = "client=> server..."; 22 char buf[256] = { 0 }; 23 Sleep(1000); 24 int len = ::send(client_socket, pbuf, strlen(pbuf), 0); 25 if (len > 0) { 26 std::cout << "send len=" << len << std::endl; 27 len = ::recv(client_socket, buf, 256, 0); 28 if (len > 0) { 29 std::cout <<"len=" << len << " data=" << buf << std::endl; 30 } 31 } 32 33 } 34 Sleep(1000); 35 closesocket(client_socket); 36 37 38 WSACleanup(); 39 return 0; 40 }
PS:会笑的人,运气通常都会比别人好。
posted on 2020-09-23 10:26 thinkinc999 阅读(311) 评论(0) 编辑 收藏 举报