IOCP模型与网络编

一。前言:
        在老师分配任务(“尝试利用IOCP模型写出服务端和客户端的代码”)给我时,脑子一片空白,并不知道什么是IOCP模型,会不会是像软件设计模式里面的工厂模式,装饰模式之类的那些呢?嘿嘿,不过好像是一个挺好玩的东西,挺好奇是什么东西来的,又是一个新知识啦~于是,开始去寻找一大堆的资料,为这个了解做准备,只是呢,有时还是想去找一本书去系统地学习一下,毕竟网络的资料还是有点零散。话说,本人学习这个模型的基础是,写过一个简单的Socket服务器及客户端程序,外加一个简单的Socket单服务器对多客户端程序,懂一点点的操作系统原理的知识。于是,本着一个学习与应用的态度开始探究这个IOCP是个什么东西。

二。提出相关问题:
       1.  IOCP模型是什么?
       2.  IOCP模型是用来解决什么问题的?它为什么存在?
       3.  使用IOCP模型需要用到哪些知识?
       4.  如何使用IOCP模型与Socket网络编程结合起来?
       5.  学会了这个模型以后与我之前写过的简单的socket程序主要有哪些不同点?

三。部分问题探究及解决:(绝大多数是个人理解,再加上个人是菜鸟,如果有什么不对的地方,欢迎指正)
       1.  什么是IOCP?什么是IOCP模型?IOCP模型有什么作用?
              1) IOCP(I/O Completion Port),常称I/O完成端口。
              2) IOCP模型属于一种通讯模型,适用于(能控制并发执行的)高负载服务器的一个技术。
              3) 通俗一点说,就是用于高效处理很多很多的客户端进行数据交换的一个模型。
              4) 或者可以说,就是能异步I/O操作的模型。
              5) 只是了解到这些会让人很糊涂,因为还是不知道它究意具体是个什么东东呢?

下面我想给大家看三个图:
第一个是IOCP的内部工作队列图。(整合于《IOCP本质论》文章,在英文的基础上加上中文对照)

第二个是程序实现IOCP模型的基本步骤。(整合于《深入解释IOCP》,加个人观点、理解、翻译)
 

第三个是使用了IOCP模型及没使用IOCP模型的程序流程图。(个人理解绘制)
 

2.  IOCP的存在理由(IOCP的优点)及技术相关有哪些?
        之前说过,很通俗地理解可以理解成是用于高效处理很多很多的客户端进行数据交换的一个模型,那么,它具体的优点有些什么呢?它到底用到了哪些技术了呢?在Windows环境下又如何去使用这些技术来编程呢?它主要使用上哪些API函数呢?呃~看来我真是一个问题多多的人,跟前面提出的相关问题变种延伸了不少的问题,好吧,下面一个个来解决。

1) 使用IOCP模型编程的优点
       ① 帮助维持重复使用的内存池。(与重叠I/O技术有关)
       ② 去除删除线程创建/终结负担。
       ③ 利于管理,分配线程,控制并发,最小化的线程上下文切换。
       ④ 优化线程调度,提高CPU和内存缓冲的命中率。

2) 使用IOCP模型编程汲及到的知识点(无先后顺序)
       ① 同步与异步
       ② 阻塞与非阻塞
       ③ 重叠I/O技术
       ④ 多线程
       ⑤ 栈、队列这两种基本的数据结构

3) 需要使用上的API函数
  ① 与SOCKET相关
       1、链接套接字动态链接库:int WSAStartup(...);
       2、创建套接字库:        SOCKET socket(...);
       3、绑字套接字:          int bind(...);
       4、套接字设为监听状态: int listen(...);
       5、接收套接字:          SOCKET accept(...);
       6、向指定套接字发送信息:int send(...);
       7、从指定套接字接收信息:int recv(...);

② 与线程相关
       1、创建线程:HANDLE CreateThread(...);

③ 重叠I/O技术相关
       1、向套接字发送数据:    int WSASend(...);
       2、向套接字发送数据包:  int WSASendFrom(...);
       3、从套接字接收数据:    int WSARecv(...);
       4、从套接字接收数据包:  int WSARecvFrom(...);

④ IOCP相关
       1、创建完成端口: HANDLE WINAPI CreateIoCompletionPort(...);
       2、关联完成端口: HANDLE WINAPI CreateIoCompletionPort(...);
       3、获取队列完成状态: BOOL WINAPI GetQueuedCompletionStatus(...);
       4、投递一个队列完成状态:BOOL WINAPI PostQueuedCompletionStatus(...);

四。完整的简单的IOCP服务器与客户端代码实例:

  1 // IOCP_TCPIP_Socket_Server.cpp
  2
  3 #include <WinSock2.h>
  4 #include <Windows.h>
  5 #include <vector>
  6 #include <iostream>
  7
  8 using namespace std;
  9
 10 #pragma comment(lib, "Ws2_32.lib")      // Socket编程需用的动态链接库
 11 #pragma comment(lib, "Kernel32.lib")    // IOCP需要用到的动态链接库
 12
 13 /**
 14  * 结构体名称:PER_IO_DATA
 15  * 结构体功能:重叠I/O需要用到的结构体,临时记录IO数据
 16  **/
 17 const int DataBuffSize  = 2 * 1024;
 18 typedef struct
 19 {
 20     OVERLAPPED overlapped;
 21     WSABUF databuff;
 22     char buffer[ DataBuffSize ];
 23     int BufferLen;
 24     int operationType;
 25 }PER_IO_OPERATEION_DATA, *LPPER_IO_OPERATION_DATA, *LPPER_IO_DATA, PER_IO_DATA;
 26
 27 /**
 28  * 结构体名称:PER_HANDLE_DATA
 29  * 结构体存储:记录单个套接字的数据,包括了套接字的变量及套接字的对应的客户端的地址。
 30  * 结构体作用:当服务器连接上客户端时,信息存储到该结构体中,知道客户端的地址以便于回访。
 31  **/
 32 typedef struct
 33 {
 34     SOCKET socket;
 35     SOCKADDR_STORAGE ClientAddr;
 36 }PER_HANDLE_DATA, *LPPER_HANDLE_DATA;
 37
 38 // 定义全局变量
 39 const int DefaultPort = 6000;
 40 vector < PER_HANDLE_DATA* > clientGroup;      // 记录客户端的向量组
 41
 42 HANDLE hMutex = CreateMutex(NULL, FALSE, NULL);
 43 DWORD WINAPI ServerWorkThread(LPVOID CompletionPortID);
 44 DWORD WINAPI ServerSendThread(LPVOID IpParam);
 45
 46 // 开始主函数
 47 int main()
 48 {
 49 // 加载socket动态链接库
 50     WORD wVersionRequested = MAKEWORD(2, 2); // 请求2.2版本的WinSock库
 51     WSADATA wsaData;    // 接收Windows Socket的结构信息
 52     DWORD err = WSAStartup(wVersionRequested, &wsaData);
 53
 54     if (0 != err){  // 检查套接字库是否申请成功
 55         cerr << "Request Windows Socket Library Error!\n";
 56         system("pause");
 57         return -1;
 58     }
 59     if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){// 检查是否申请了所需版本的套接字库
 60         WSACleanup();
 61         cerr << "Request Windows Socket Version 2.2 Error!\n";
 62         system("pause");
 63         return -1;
 64     }
 65
 66 // 创建IOCP的内核对象
 67     /**
 68      * 需要用到的函数的原型:
 69      * HANDLE WINAPI CreateIoCompletionPort(
 70      *    __in   HANDLE FileHandle,     // 已经打开的文件句柄或者空句柄,一般是客户端的句柄
 71      *    __in   HANDLE ExistingCompletionPort, // 已经存在的IOCP句柄
 72      *    __in   ULONG_PTR CompletionKey,   // 完成键,包含了指定I/O完成包的指定文件
 73      *    __in   DWORD NumberOfConcurrentThreads // 真正并发同时执行最大线程数,一般推介是CPU核心数*2
 74      * );
 75      **/
 76     HANDLE completionPort = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 0);
 77     if (NULL == completionPort){    // 创建IO内核对象失败
 78         cerr << "CreateIoCompletionPort failed. Error:" << GetLastError() << endl;
 79         system("pause");
 80         return -1;
 81     }
 82
 83 // 创建IOCP线程--线程里面创建线程池
 84
 85     // 确定处理器的核心数量
 86     SYSTEM_INFO mySysInfo;
 87     GetSystemInfo(&mySysInfo);
 88
 89     // 基于处理器的核心数量创建线程
 90     for(DWORD i = 0; i < (mySysInfo.dwNumberOfProcessors * 2); ++i){
 91         // 创建服务器工作器线程,并将完成端口传递到该线程
 92         HANDLE ThreadHandle = CreateThread(NULL, 0, ServerWorkThread, completionPort, 0, NULL);
 93         if(NULL == ThreadHandle){
 94             cerr << "Create Thread Handle failed. Error:" << GetLastError() << endl;
 95         system("pause");
 96             return -1;
 97         }
 98         CloseHandle(ThreadHandle);
 99     }
100
101 // 建立流式套接字
102     SOCKET srvSocket = socket(AF_INET, SOCK_STREAM, 0);
103
104 // 绑定SOCKET到本机
105     SOCKADDR_IN srvAddr;
106     srvAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
107     srvAddr.sin_family = AF_INET;
108     srvAddr.sin_port = htons(DefaultPort);
109     int bindResult = bind(srvSocket, (SOCKADDR*)&srvAddr, sizeof(SOCKADDR));
110     if(SOCKET_ERROR == bindResult){
111         cerr << "Bind failed. Error:" << GetLastError() << endl;
112         system("pause");
113         return -1;
114     }
115
116 // 将SOCKET设置为监听模式
117     int listenResult = listen(srvSocket, 10);
118     if(SOCKET_ERROR == listenResult){
119         cerr << "Listen failed. Error: " << GetLastError() << endl;
120         system("pause");
121         return -1;
122     }
123
124 // 开始处理IO数据
125     cout << "本服务器已准备就绪,正在等待客户端的接入...\n";
126
127     // 创建用于发送数据的线程
128     HANDLE sendThread = CreateThread(NULL, 0, ServerSendThread, 0, 0, NULL);
129
130     while(true){
131         PER_HANDLE_DATA * PerHandleData = NULL;
132         SOCKADDR_IN saRemote;
133         int RemoteLen;
134         SOCKET acceptSocket;
135
136         // 接收连接,并分配完成端,这儿可以用AcceptEx()
137         RemoteLen = sizeof(saRemote);
138         acceptSocket = accept(srvSocket, (SOCKADDR*)&saRemote, &RemoteLen);
139         if(SOCKET_ERROR == acceptSocket){   // 接收客户端失败
140             cerr << "Accept Socket Error: " << GetLastError() << endl;
141             system("pause");
142             return -1;
143         }
144
145         // 创建用来和套接字关联的单句柄数据信息结构
146         PerHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA));  // 在堆中为这个PerHandleData申请指定大小的内存
147         PerHandleData -> socket = acceptSocket;
148         memcpy (&PerHandleData -> ClientAddr, &saRemote, RemoteLen);
149         clientGroup.push_back(PerHandleData);       // 将单个客户端数据指针放到客户端组中
150
151         // 将接受套接字和完成端口关联
152         CreateIoCompletionPort((HANDLE)(PerHandleData -> socket), completionPort, (DWORD)PerHandleData, 0);
153
154
155         // 开始在接受套接字上处理I/O使用重叠I/O机制
156         // 在新建的套接字上投递一个或多个异步
157         // WSARecv或WSASend请求,这些I/O请求完成后,工作者线程会为I/O请求提供服务
158         // 单I/O操作数据(I/O重叠)
159         LPPER_IO_OPERATION_DATA PerIoData = NULL;
160         PerIoData = (LPPER_IO_OPERATION_DATA)GlobalAlloc(GPTR, sizeof(PER_IO_OPERATEION_DATA));
161         ZeroMemory(&(PerIoData -> overlapped), sizeof(OVERLAPPED));
162         PerIoData->databuff.len = 1024;
163         PerIoData->databuff.buf = PerIoData->buffer;
164         PerIoData->operationType = 0;    // read
165
166         DWORD RecvBytes;
167         DWORD Flags = 0;
168         WSARecv(PerHandleData->socket, &(PerIoData->databuff), 1, &RecvBytes, &Flags, &(PerIoData->overlapped), NULL);
169     }
170
171     system("pause");
172     return 0;
173 }
174
175 // 开始服务工作线程函数
176 DWORD WINAPI ServerWorkThread(LPVOID IpParam)
177 {
178     HANDLE CompletionPort = (HANDLE)IpParam;
179     DWORD BytesTransferred;
180     LPOVERLAPPED IpOverlapped;
181     LPPER_HANDLE_DATA PerHandleData = NULL;
182     LPPER_IO_DATA PerIoData = NULL;
183     DWORD RecvBytes;
184     DWORD Flags = 0;
185     BOOL bRet = false;
186
187     while(true){
188         bRet = GetQueuedCompletionStatus(CompletionPort, &BytesTransferred, (PULONG_PTR)&PerHandleData, (LPOVERLAPPED*)&IpOverlapped, INFINITE);
189         if(bRet == 0){
190             cerr << "GetQueuedCompletionStatus Error: " << GetLastError() << endl;
191             return -1;
192         }
193         PerIoData = (LPPER_IO_DATA)CONTAINING_RECORD(IpOverlapped, PER_IO_DATA, overlapped);
194
195         // 检查在套接字上是否有错误发生
196         if(0 == BytesTransferred){
197             closesocket(PerHandleData->socket);
198             GlobalFree(PerHandleData);
199             GlobalFree(PerIoData);
200             continue;
201         }
202
203         // 开始数据处理,接收来自客户端的数据
204         WaitForSingleObject(hMutex,INFINITE);
205         cout << "A Client says: " << PerIoData->databuff.buf << endl;
206         ReleaseMutex(hMutex);
207
208         // 为下一个重叠调用建立单I/O操作数据
209         ZeroMemory(&(PerIoData->overlapped), sizeof(OVERLAPPED)); // 清空内存
210         PerIoData->databuff.len = 1024;
211         PerIoData->databuff.buf = PerIoData->buffer;
212         PerIoData->operationType = 0;    // read
213         WSARecv(PerHandleData->socket, &(PerIoData->databuff), 1, &RecvBytes, &Flags, &(PerIoData->overlapped), NULL);
214     }
215
216     return 0;
217 }
218
219
220 // 发送信息的线程执行函数
221 DWORD WINAPI ServerSendThread(LPVOID IpParam)
222 {
223     while(1){
224         char talk[200];
225         gets(talk);
226         int len;
227         for (len = 0; talk[len] != ‘\0‘; ++len){
228             // 找出这个字符组的长度
229         }
230         talk[len] = ‘\n‘;
231         talk[++len] = ‘\0‘;
232         printf("I Say:");
233         cout << talk;
234         WaitForSingleObject(hMutex,INFINITE);
235         for(int i = 0; i < clientGroup.size(); ++i){
236             send(clientGroup[i]->socket, talk, 200, 0);  // 发送信息
237         }
238         ReleaseMutex(hMutex);
239     }
240     return 0;
241 }  
  1 // IOCP_TCPIP_Socket_Client.cpp
  2
  3 #include <iostream>
  4 #include <cstdio>
  5 #include <string>
  6 #include <cstring>
  7 #include <winsock2.h>
  8 #include <Windows.h>
  9
 10 using namespace std;
 11
 12 #pragma comment(lib, "Ws2_32.lib")      // Socket编程需用的动态链接库
 13
 14 SOCKET sockClient;      // 连接成功后的套接字
 15 HANDLE bufferMutex;     // 令其能互斥成功正常通信的信号量句柄
 16 const int DefaultPort = 6000;
 17
 18 int main()
 19 {
 20 // 加载socket动态链接库(dll)
 21     WORD wVersionRequested;
 22     WSADATA wsaData;    // 这结构是用于接收Wjndows Socket的结构信息的
 23     wVersionRequested = MAKEWORD( 2, 2 );   // 请求2.2版本的WinSock库
 24     int err = WSAStartup( wVersionRequested, &wsaData );
 25     if ( err != 0 ) {   // 返回值为零的时候是表示成功申请WSAStartup
 26         return -1;
 27     }
 28     if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) { // 检查版本号是否正确
 29         WSACleanup( );
 30         return -1;
 31     }
 32
 33 // 创建socket操作,建立流式套接字,返回套接字号sockClient
 34      sockClient = socket(AF_INET, SOCK_STREAM, 0);
 35      if(sockClient == INVALID_SOCKET) {
 36         printf("Error at socket():%ld\n", WSAGetLastError());
 37         WSACleanup();
 38         return -1;
 39       }
 40
 41 // 将套接字sockClient与远程主机相连
 42     // int connect( SOCKET s,  const struct sockaddr* name,  int namelen);
 43     // 第一个参数:需要进行连接操作的套接字
 44     // 第二个参数:设定所需要连接的地址信息
 45     // 第三个参数:地址的长度
 46     SOCKADDR_IN addrSrv;
 47     addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");      // 本地回路地址是127.0.0.1;
 48     addrSrv.sin_family = AF_INET;
 49     addrSrv.sin_port = htons(DefaultPort);
 50     while(SOCKET_ERROR == connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR))){
 51         // 如果还没连接上服务器则要求重连
 52         cout << "服务器连接失败,是否重新连接?(Y/N):";
 53         char choice;
 54         while(cin >> choice && (!((choice != ‘Y‘ && choice == ‘N‘) || (choice == ‘Y‘ && choice != ‘N‘)))){
 55             cout << "输入错误,请重新输入:";
 56             cin.sync();
 57             cin.clear();
 58         }
 59         if (choice == ‘Y‘){
 60             continue;
 61         }
 62         else{
 63             cout << "退出系统中...";
 64             system("pause");
 65             return 0;
 66         }
 67     }
 68     cin.sync();
 69     cout << "本客户端已准备就绪,用户可直接输入文字向服务器反馈信息。\n";
 70
 71     send(sockClient, "\nAttention: A Client has enter...\n", 200, 0);
 72
 73     bufferMutex = CreateSemaphore(NULL, 1, 1, NULL);
 74
 75     DWORD WINAPI SendMessageThread(LPVOID IpParameter);
 76     DWORD WINAPI ReceiveMessageThread(LPVOID IpParameter);
 77
 78     HANDLE sendThread = CreateThread(NULL, 0, SendMessageThread, NULL, 0, NULL);
 79     HANDLE receiveThread = CreateThread(NULL, 0, ReceiveMessageThread, NULL, 0, NULL);
 80
 81
 82     WaitForSingleObject(sendThread, INFINITE);  // 等待线程结束
 83     closesocket(sockClient);
 84     CloseHandle(sendThread);
 85     CloseHandle(receiveThread);
 86     CloseHandle(bufferMutex);
 87     WSACleanup();   // 终止对套接字库的使用
 88
 89     printf("End linking...\n");
 90     printf("\n");
 91     system("pause");
 92     return 0;
 93 }
 94
 95
 96 DWORD WINAPI SendMessageThread(LPVOID IpParameter)
 97 {
 98     while(1){
 99         string talk;
100         getline(cin, talk);
101         WaitForSingleObject(bufferMutex, INFINITE);     // P(资源未被占用)
102         if("quit" == talk){
103             talk.push_back(‘\0‘);
104             send(sockClient, talk.c_str(), 200, 0);
105             break;
106         }
107         else{
108             talk.append("\n");
109         }
110         printf("\nI Say:(\"quit\"to exit):");
111         cout << talk;
112         send(sockClient, talk.c_str(), 200, 0); // 发送信息
113         ReleaseSemaphore(bufferMutex, 1, NULL);     // V(资源占用完毕)
114     }
115     return 0;
116 }
117
118
119 DWORD WINAPI ReceiveMessageThread(LPVOID IpParameter)
120 {
121     while(1){
122         char recvBuf[300];
123         recv(sockClient, recvBuf, 200, 0);
124         WaitForSingleObject(bufferMutex, INFINITE);     // P(资源未被占用)
125
126         printf("%s Says: %s", "Server", recvBuf);       // 接收信息
127
128         ReleaseSemaphore(bufferMutex, 1, NULL);     // V(资源占用完毕)
129     }
130     return 0;
131 } 

五。本次学习资料
       几翻周折,终于写出一个比较简单的IOCP模型的服务器与客户端啦,并且也大概了解这个模型的思路啦~没有买书的娃,伤不起啊,只能从网上搜罗资料,幸好有这些文章在,最后为下列这些文章的作者说声谢谢~

转http://blog.csdn.net/neicole/article/details/7549497

时间: 2024-10-13 10:08:25

IOCP模型与网络编的相关文章

IOCP模型与网络编程

IOCP模型与网络编程 一.前言:        在老师分配任务("尝试利用IOCP模型写出服务端和客户端的代码")给我时,脑子一片空白,并不知道什么是IOCP模型,会不会是像软件设计模式里面的工厂模式,装饰模式之类的那些呢?嘿嘿,不过好像是一个挺好玩的东西,挺好奇是什么东西来的,又是一个新知识啦~于是,开始去寻找一大堆的资料,为这个了解做准备,只是呢,有时还是想去找一本书去系统地学习一下,毕竟网络的资料还是有点零散.话说,本人学习这个模型的基础是,写过一个简单的Socket服务器及客

网络编程之IO模型——非阻塞IO

网络编程之IO模型--非阻塞IO 非阻塞IO(non-blocking IO) Linux下,可以通过设置socket使其变为non-blocking.当对一个non-blocking socket执行读操作时,流程是这个样子: 从图中可以看出,当用户进程发出read操作时,如果kernel中的数据还没有准备好,那么它并不会block用户进程,而是立刻返回一个error.从用户进程角度讲 ,它发起一个read操作后,并不需要等待,而是马上就得到了一个结果.用户进程判断结果是一个error时,它就

网络编程之IO模型——IO模型比较分析

网络编程之IO模型--IO模型比较分析 IO模型比较分析 到目前为止,已经将四个IO Model都介绍完了.现在回过头来回答最初的那几个问题:blocking和non-blocking的区别在哪,synchronous IO和asynchronous IO的区别在哪. 先回答最简单的这个:blocking vs non-blocking.前面的介绍中其实已经很明确的说明了这两者的区别.调用blocking IO会一直block住对应的进程直到操作完成,而non-blocking IO在kerne

网络编程之IO模型——selectors模块

网络编程之IO模型--selectors模块 一.了解select,poll,epoll IO复用:为了解释这个名词,首先来理解下复用这个概念,复用也就是共用的意思,这样理解还是有些抽象, 为此,咱们来理解下复用在通信领域的使用,在通信领域中为了充分利用网络连接的物理介质. 往往在同一条网络链路上采用时分复用或频分复用的技术使其在同一链路上传输多路信号,到这里我们就基本上理解了复用的含义, 即公用某个"介质"来尽可能多的做同一类(性质)的事,那IO复用的"介质"是什

(转)linux网络编程之IO模型

原文:http://www.cnblogs.com/kunhu/p/3624000.html 1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式:同步:      所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回.也就是必须一件一件事做,等前一件做完了才能做下一件事. 例如普通B/S模式(同步):提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事 异步:  

IOCP模型总结(总结回顾)

IOCP旧代码重提,最近一直在玩其他方面的东东,时不时回顾一下,收益多多. IOCP(I/O Completion Port,I/O完成端口)是性能最好的一种I/O模型.它是应用程序使用线程池处理异步I/O请求的一种机制.在处理多个并发的异步I/O请求时,以往的模型都是在接收请求是创建一个线程来应答请求.这样就有很多的线程并行地运行在系统中.而这些线程都是可运行的,Windows内核花费大量的时间在进行线程的上下文切换,并没有多少时间花在线程运行上.再加上创建新线程的开销比较大,所以造成了效率的

Window下高性能IOCP模型队列多线程下应用

IOCP,先从概念上认识一下.IOCP全称I/O Completion Port,中文译为I/O完成端口.是Windows平台最高效的I/O模块,现在IIS服务器,就采用IOCP模型.IOCP是一个异步I/O的API,它可以高效地将I/O事件通知给应用程序.与使用select()或是其它异步方法不同的是,现在很多书,文字都直接将IOCP模块和网络编程关联起来,好像IOCP就是和网络打交道的.典型的IOCP模型的使用,是 将一个套接字(socket)与一个完成端口关联了起来,当一个网络事件发生的时

linux网络编程之TCP/IP基础篇(一)

从今天起,将会接触到网络编程,平台是linux,实现语言C语言,最后将会实现一个简易的miniftp服务器. 主要的内容安排为:linux网络编程之TCP/IP基础篇,SOCKET编程篇,进程间通信篇,线程篇,实战ftp篇. 1.ISO/OSI参考模型:open system interconnection开放系统互联模型是由OSI(international organization for standardization )国际标准化组织定义的网络分层模型,共七层. 各层的具体含义: 物理层

winsock编程IOCP模型实现代码

winsock编程IOCP模型实现代码 话不多说,上代码.借鉴<windows核心编程>部分源码和CSDN小猪部分代码. stdafx.h依赖头文件: 1 #include <iostream> 2 #include <WinSock2.h> 3 #include <MSWSock.h> 4 #include <vector> 5 #include "Singleton.h" 6 #include "IOCPWrap