zoukankan      html  css  js  c++  java
  • 单进程单线程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:会笑的人,运气通常都会比别人好。
  • 相关阅读:
    【leetcode】Recover Binary Search Tree
    【leetcode】Dungeon Game
    【leetcode】Text Justification
    【leetcode】Largest Number
    【leetcode】Merge k Sorted Lists
    【leetcode】Reverse Nodes in k-Group
    【leetcode】Multiply Strings
    【leetcode】Unique Binary Search Trees II
    hdu 1885 bfs+状压
    hdu 1429 bfs+状态压缩
  • 原文地址:https://www.cnblogs.com/thinkinc999/p/13716711.html
Copyright © 2011-2022 走看看