首页 > 编程语言 > 详细

单进程单线程IOCP的实现(含客户端和服务端)

时间:2020-09-23 11:59:16      阅读:80      评论:0      收藏:0      [点我收藏+]

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 sk_listen_;
 18 HANDLE h_iocp_;
 19 
 20 
 21 
 22 enum CPK_TYPE {
 23     CPK_ACCEPT = 1000, //接收请求的完成标识
 24     CPK_CLOSE,
 25 };
 26 
 27 
 28 class io_context : public OVERLAPPED
 29 {
 30 public:
 31     io_context() {
 32         memset(static_cast<OVERLAPPED *>(this), 0, sizeof(OVERLAPPED));
 33         client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 34         buf_ = new char[4096];
 35         w_buf_.buf = buf_;
 36         w_buf_.len = 4096;
 37     }
 38     virtual ~io_context() {
 39 
 40     }
 41 
 42     int op_code = 0;
 43     WSABUF w_buf_;
 44     char* buf_;
 45     SOCKET client_socket;
 46 };
 47 
 48 
 49 
 50 
 51 void init_net_func(int s) {
 52     GUID guidAcceptEx = WSAID_ACCEPTEX;
 53     DWORD bytes = 0;
 54     if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &guidAcceptEx,
 55         sizeof(GUID), &accept_ex_, sizeof(LPFN_ACCEPTEX), &bytes, NULL,
 56         NULL) == SOCKET_ERROR) {
 57         throw std::exception("get acceptex interface error", GetLastError());
 58     }
 59 }
 60 
 61 
 62 
 63 void post_accept()
 64 {
 65 
 66 
 67     io_context* pIoContent = new io_context;
 68 
 69     pIoContent->op_code = CPK_ACCEPT;
 70 
 71     DWORD len = 0;
 72 
 73     if (!accept_ex_(sk_listen_, pIoContent->client_socket, pIoContent->buf_, 0,
 74         sizeof(sockaddr_in) + 16, sizeof(sockaddr_in) + 16, &len,
 75         pIoContent)) {
 76         if (WSA_IO_PENDING != WSAGetLastError()) {
 77             throw std::exception("acceptex error", GetLastError());
 78         }
 79     }
 80 }
 81 
 82 
 83 unsigned int __stdcall work_thread(void* lParam)
 84 {
 85     LPOVERLAPPED overlapped = NULL;
 86     ULONG_PTR cl_key = 0;
 87     DWORD recv_bytes = 0;
 88     while (true) {
 89         BOOL ret = GetQueuedCompletionStatus(h_iocp_, &recv_bytes, &cl_key,
 90             &overlapped, 0);
 91 
 92 
 93 
 94         if (ret) {
 95             std::cout << "recv_bytes=" << recv_bytes << std::endl;
 96             io_context* p_io_content = (io_context*)overlapped;
 97 
 98             if (p_io_content->op_code == 2) {
 99                 std::cout << "send ok" << std::endl;
100             }
101 
102             if (p_io_content->op_code == 1) {
103                 std::cout << p_io_content->buf_ << std::endl;
104 
105 
106 
107                 DWORD send_len = 0;
108                 DWORD flags = 0;
109 
110                 p_io_content->op_code = 2;
111                 p_io_content->w_buf_.len = strlen(p_io_content->w_buf_.buf) - 1;
112 
113                 if (WSASend(p_io_content->client_socket, &p_io_content->w_buf_,
114                     1, &send_len, flags, p_io_content,
115                     NULL) == SOCKET_ERROR) {
116                     if (WSAGetLastError() != WSA_IO_PENDING) {
117                         throw std::exception("send error", GetLastError());
118                     }
119                 }
120 
121             }
122 
123             if (CPK_ACCEPT == cl_key) {
124                 std::cout << "1" << std::endl;
125                 //post_accept();
126 
127                 if (!CreateIoCompletionPort((HANDLE)p_io_content->client_socket, h_iocp_, NULL,
128                     1)) {
129                     throw std::exception("bind listen to iocp", GetLastError());
130                 }
131 
132                 DWORD recv_len = 0;
133                 DWORD flags = 0;
134                 p_io_content->op_code = 1;
135 
136                 if (WSARecv(p_io_content->client_socket, &p_io_content->w_buf_,
137                     1, &recv_len, &flags, p_io_content, NULL) == SOCKET_ERROR) {
138                     if (WSAGetLastError() != WSA_IO_PENDING) {
139                         throw std::exception("recv error", GetLastError());
140                     }
141                 }
142             }
143 
144         }
145     }
146 
147     return 0;
148 }
149 
150 int main()
151 {
152     WSADATA wsa;
153     WSAStartup(MAKEWORD(2, 2), &wsa);
154 
155     sk_listen_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
156 
157     assert(sk_listen_ != INVALID_SOCKET);
158     sockaddr_in addr = { 0 };
159     addr.sin_family = AF_INET;
160     addr.sin_addr.s_addr = inet_addr("127.0.0.1");
161     addr.sin_port = htons(12345);
162 
163     if (0 != bind(sk_listen_, (struct sockaddr *)&addr, sizeof(sockaddr))) {
164         throw std::exception("bind error", GetLastError());
165     }
166     int work_thread_num_ = 1;
167     h_iocp_ = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL,
168         work_thread_num_);
169     if (!h_iocp_) {
170         throw std::exception("create iocp error", GetLastError());
171     }
172     init_net_func(sk_listen_);
173     listen(sk_listen_, 0);
174 
175 
176     //handle_work_threads_.resize(work_thread_num_);
177     //for (int i = 0; i < work_thread_num_; i++) 
178     {
179         post_accept();
180         //_beginthreadex(NULL, 0, work_thread, 0, 0, NULL);
181     }
182 
183     if (!CreateIoCompletionPort((HANDLE)sk_listen_, h_iocp_, CPK_ACCEPT, work_thread_num_)) {
184         throw std::exception("bind listen to iocp", GetLastError());
185     }
186 
187     work_thread(NULL);
188 
189     //while (true) {
190     //    Sleep(1000);
191     //}
192 
193     WSACleanup();
194 
195 }
196 
197 


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 << buf << std::endl;
 30             }
 31         }
 32 
 33     }
 34     Sleep(1000);
 35     closesocket(client_socket);
 36 
 37 
 38     WSACleanup();
 39     return 0;
 40 }

单进程单线程IOCP的实现(含客户端和服务端)

原文:https://www.cnblogs.com/thinkinc999/p/13716711.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!