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 "IOCPWrapper.h"
 7 #include "OverlappedIOInfo.h"
 8 #include "TaskSvc.h"
 9
10 using namespace std;

  其中,TaskSvc.h、Singleton.h源码可以在我的blog里面找到。

  IOCPWrapper.h源码:

 1 /******************************************************************************
 2 Module:  IOCP.h
 3 Notices: Copyright (c) 2007 Jeffrey Richter & Christophe Nasarre
 4 Purpose: This class wraps an I/O Completion Port.
 5 Revise:    IOCP封装类,由《windows核心编程》第10章示例程序源码改编所得
 6 ******************************************************************************/
 7 #pragma once
 8
 9 class CIOCP
10 {
11 public:
12    CIOCP(int nMaxConcurrency = -1)
13    {
14        m_hIOCP = NULL;
15        if (nMaxConcurrency != -1)
16            Create(nMaxConcurrency);
17    }
18    ~CIOCP()
19    {
20        if (m_hIOCP != NULL)
21            VERIFY(CloseHandle(m_hIOCP));
22    }
23
24    //关闭IOCP
25    BOOL Close()
26    {
27        BOOL bResult = CloseHandle(m_hIOCP);
28        m_hIOCP = NULL;
29        return(bResult);
30    }
31
32    //创建IOCP,nMaxConcurrency指定最大线程并发数量,0默认为cpu数量
33    BOOL Create(int nMaxConcurrency = 0)
34    {
35        m_hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, nMaxConcurrency);
36        ASSERT(m_hIOCP != NULL);
37        return(m_hIOCP != NULL);
38    }
39
40    //为设备(文件、socket、邮件槽、管道等)关联一个IOCP
41    BOOL AssociateDevice(HANDLE hDevice, ULONG_PTR CompKey)
42    {
43        BOOL fOk = (CreateIoCompletionPort(hDevice, m_hIOCP, CompKey, 0) == m_hIOCP);
44        ASSERT(fOk);
45        return(fOk);
46    }
47
48    //为socket关联一个IOCP
49    BOOL AssociateSocket(SOCKET hSocket, ULONG_PTR CompKey)
50    {
51        return(AssociateDevice((HANDLE) hSocket, CompKey));
52    }
53
54    //为iocp传递事件通知
55    BOOL PostStatus(ULONG_PTR CompKey, DWORD dwNumBytes = 0,OVERLAPPED* po = NULL)
56    {
57        BOOL fOk = PostQueuedCompletionStatus(m_hIOCP, dwNumBytes, CompKey, po);
58        ASSERT(fOk);
59        return(fOk);
60    }
61
62    //从IO完成队列中获取事件通知。IO完成队列无事件时,该函数将阻塞
63    BOOL GetStatus(ULONG_PTR* pCompKey, PDWORD pdwNumBytes,OVERLAPPED** ppo, DWORD dwMilliseconds = INFINITE)
64    {
65        return(GetQueuedCompletionStatus(m_hIOCP, pdwNumBytes,pCompKey, ppo, dwMilliseconds));
66    }
67
68    //获取IOCP对象
69    const HANDLE  GetIOCP()
70    {
71        return m_hIOCP;
72    }
73 private:
74     //IOCP句柄
75    HANDLE m_hIOCP;
76 };
77
78 ///////////////////////////////// End of File /////////////////////////////////

OverlappedIOInfo.h源码

 1 /******************************************************************************
 2 Module:  OverlappedIOInfo.h
 3 Notices: Copyright (c) 20161201  whg
 4 Purpose:
 5 IOCP网络编程模型中,需要用到GetQueuedCompletionStatus函数获取已完成事件。
 6 但该函数的返回参数无socket或buffer的描述信息。
 7
 8 一个简单的解决办法,创建一个新的结构,该结构第一个参数是OVERLAPPED。
 9 由于AcceptEx、WSASend等重叠IO操作传入的是Overlapped结构体的地址,调用AcceptEx等重叠IO操作,
10 在Overlapped结构体后面开辟新的空间,写入socket或buffer的信息,即可将socket或buffer的信息由
11 GetQueuedCompletionStatus带回。
12
13 参考《windows核心编程》和CSDN PiggyXP
14 ******************************************************************************/
15
16 #pragma once
17
18 #define MAXBUF 8*1024
19
20 enum IOOperType{
21     TYPE_ACP,            //accept事件到达,有新连接请求
22     TYPE_RECV,            //数据接收事件
23     TYPE_SEND,            //数据发送事件
24     TYPE_CLOSE,            //关闭事件
25     TYPE_NO_OPER
26 };
27
28 class COverlappedIOInfo :    public OVERLAPPED
29 {
30 public:
31     COverlappedIOInfo(void)
32     {
33         m_sSock = INVALID_SOCKET;
34         ResetOverlapped();
35         ResetRecvBuffer();
36         ResetSendBuffer();
37     }
38     ~COverlappedIOInfo(void)
39     {
40         if (m_sSock != INVALID_SOCKET)
41         {
42             closesocket(m_sSock);
43             m_sSock = INVALID_SOCKET;
44         }
45     }
46     void ResetOverlapped()
47     {
48         Internal = InternalHigh = 0;
49         Offset = OffsetHigh = 0;
50         hEvent = NULL;
51     }
52     void ResetRecvBuffer()
53     {
54         ZeroMemory(m_cRecvBuf,MAXBUF);
55         m_recvBuf.buf = m_cRecvBuf;
56         m_recvBuf.len = MAXBUF;
57     }
58     void ResetSendBuffer()
59     {
60         ZeroMemory(m_cSendBuf,MAXBUF);
61         m_sendBuf.buf = m_cSendBuf;
62         m_sendBuf.len = MAXBUF;
63     }
64 public:
65     //套接字
66     SOCKET        m_sSock;
67     //接收缓冲区,用于AcceptEx、WSARecv操作
68     WSABUF        m_recvBuf;
69     char        m_cRecvBuf[MAXBUF];
70     //发送缓冲区,用于WSASend操作
71     WSABUF        m_sendBuf;
72     char        m_cSendBuf[MAXBUF];
73     //对端地址
74     sockaddr_in    m_addr;
75 };

server.h

 1 #pragma once
 2
 3
 4 class CServer:public CTaskSvc
 5 {
 6 #define ACCEPT_SOCKET_NUM  10
 7
 8 public:
 9     CServer(void);
10     ~CServer(void);
11     bool    StartListen(unsigned short port,std::string ip);
12
13 protected:
14     virtual void svc();
15
16 private:
17     //启动CPU*2个线程,返回已启动线程个数
18     UINT    StartThreadPull();
19     //获取AcceptEx和GetAcceptExSockaddrs函数指针
20     bool    GetLPFNAcceptEXAndGetAcceptSockAddrs();
21     //利用AcceptEx监听accept请求
22     bool    PostAccept(COverlappedIOInfo* ol);
23     //处理accept请求,NumberOfBytes=0表示没有收到第一帧数据,>0表示收到第一帧数据
24     bool    DoAccept(COverlappedIOInfo* ol,DWORD NumberOfBytes=0);
25     //投递recv请求
26     bool    PostRecv(COverlappedIOInfo* ol);
27     //处理recv请求
28     bool    DoRecv(COverlappedIOInfo* ol);
29     //从已连接socket列表中移除socket及释放空间
30     bool    DeleteLink(SOCKET s);
31     //释放3个部分步骤:
32     //1:清空IOCP线程队列,退出线程
33     //2: 清空等待accept的套接字m_vecAcps
34     //3: 清空已连接的套接字m_vecContInfo并清空缓存
35     void    CloseServer();
36 private:
37     //winsock版本类型
38     WSAData                        m_wsaData;
39     //端口监听套接字
40     SOCKET                        m_sListen;
41     //等待accept的套接字,这些套接字是没有使用过的,数量为ACCEPT_SOCKET_NUM。同时会有10个套接字等待accept
42     std::vector<SOCKET>            m_vecAcps;
43     //已建立连接的信息,每个结构含有一个套接字、发送缓冲和接收缓冲,以及对端地址
44     std::vector<COverlappedIOInfo*>    m_vecContInfo;
45     //操作vector的互斥访问锁
46     CThreadLockCs                m_lsc;
47     //IOCP封装类
48     CIOCP                        m_iocp;
49     //AcceptEx函数指针
50     LPFN_ACCEPTEX                m_lpfnAcceptEx;
51     //GetAcceptSockAddrs函数指针
52     LPFN_GETACCEPTEXSOCKADDRS    m_lpfnGetAcceptSockAddrs;
53 };
54
55 typedef CSingleton<CServer> SERVER;

server.cpp

  1 #include "StdAfx.h"
  2 #include "Server.h"
  3
  4 CServer::CServer(void)
  5 {
  6     m_lpfnAcceptEx = NULL;
  7     m_lpfnGetAcceptSockAddrs = NULL;
  8     WSAStartup(MAKEWORD(2,2),&m_wsaData);
  9 }
 10
 11 CServer::~CServer(void)
 12 {
 13     CloseServer();
 14     WSACleanup();
 15 }
 16
 17 bool CServer::StartListen(unsigned short port,std::string ip)
 18 {
 19     //listen socket需要将accept操作投递到完成端口,因此,listen socket属性必须有重叠IO
 20     m_sListen = WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,0,WSA_FLAG_OVERLAPPED);
 21     if(m_sListen == INVALID_SOCKET)
 22     {
 23         cout<<"WSASocket create socket error"<<endl;
 24         return false;
 25     }
 26     //创建并设置IOCP并发线程数量
 27     if (m_iocp.Create() == FALSE)
 28     {
 29         cout<<"IOCP create error,error code "<<WSAGetLastError()<<endl;
 30         return false;
 31     }
 32     //将listen socket绑定至iocp
 33     if (!m_iocp.AssociateSocket(m_sListen,TYPE_ACP))
 34     {
 35         cout<<"iocp Associate listen Socket error"<<endl;
 36         return false;
 37     }
 38     sockaddr_in service;
 39     service.sin_family = AF_INET;
 40     service.sin_port = htons(port);
 41     if (ip.empty())
 42     {
 43         service.sin_addr.s_addr = INADDR_ANY;
 44     }
 45     else
 46     {
 47         service.sin_addr.s_addr = inet_addr(ip.c_str());
 48     }
 49
 50     if (bind(m_sListen,(sockaddr*)&service,sizeof(service)) == SOCKET_ERROR)
 51     {
 52         cout<<"bind() error,error code "<<WSAGetLastError()<<endl;
 53         return false;
 54     }
 55     cout<<"bind ok!"<<endl;
 56
 57     if (listen(m_sListen,SOMAXCONN) == SOCKET_ERROR)
 58     {
 59         cout<<"listen() error,error code "<<WSAGetLastError()<<endl;
 60         return false;
 61     }
 62     cout<<"listen ok!"<<endl;
 63     //启动工作者线程
 64     int threadnum = StartThreadPull();
 65     cout<<"启动工作者线程,num="<<threadnum<<endl;
 66     //获取AcceptEx和GetAcceptSockAddrs函数指针
 67     if (!GetLPFNAcceptEXAndGetAcceptSockAddrs())
 68     {
 69         return false;
 70     }
 71     //创建10个acceptex
 72     for (int i=0;i<ACCEPT_SOCKET_NUM;i++)
 73     {
 74         //用accept
 75         COverlappedIOInfo* ol = new COverlappedIOInfo;
 76         if (!PostAccept(ol))
 77         {
 78             delete ol;
 79             return false;
 80         }
 81     }
 82 }
 83
 84 bool CServer::GetLPFNAcceptEXAndGetAcceptSockAddrs()
 85 {
 86     DWORD BytesReturned = 0;
 87     //获取AcceptEx函数指针
 88     GUID GuidAcceptEx = WSAID_ACCEPTEX;
 89     if (SOCKET_ERROR == WSAIoctl(
 90         m_sListen,
 91         SIO_GET_EXTENSION_FUNCTION_POINTER,
 92         &GuidAcceptEx,
 93         sizeof(GuidAcceptEx),
 94         &m_lpfnAcceptEx,
 95         sizeof(m_lpfnAcceptEx),
 96         &BytesReturned,
 97         NULL,NULL))
 98     {
 99         cout<<"WSAIoctl get AcceptEx function error,error code "<<WSAGetLastError()<<endl;
100         return false;
101     }
102
103     //获取GetAcceptexSockAddrs函数指针
104     GUID GuidGetAcceptexSockAddrs = WSAID_GETACCEPTEXSOCKADDRS;
105     if (SOCKET_ERROR == WSAIoctl(
106         m_sListen,
107         SIO_GET_EXTENSION_FUNCTION_POINTER,
108         &GuidGetAcceptexSockAddrs,
109         sizeof(GuidGetAcceptexSockAddrs),
110         &m_lpfnGetAcceptSockAddrs,
111         sizeof(m_lpfnGetAcceptSockAddrs),
112         &BytesReturned,
113         NULL,NULL))
114     {
115         cout<<"WSAIoctl get GetAcceptexSockAddrs function error,error code "<<WSAGetLastError()<<endl;
116         return false;
117     }
118     return true;
119 }
120
121 bool CServer::PostAccept(COverlappedIOInfo* ol)
122 {
123     if (m_lpfnAcceptEx == NULL)
124     {
125         cout << "m_lpfnAcceptEx is NULL"<<endl;
126         return false;
127     }
128     SOCKET s = ol->m_sSock;
129     ol->ResetRecvBuffer();
130     ol->ResetOverlapped();
131     ol->ResetSendBuffer();
132     ol->m_sSock = WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,0,WSA_FLAG_OVERLAPPED);
133     if (ol->m_sSock == INVALID_SOCKET)
134     {
135         cout<<"WSASocket error ,error code "<<WSAGetLastError()<<endl;
136         return false;
137     }
138     //这里建立的socket用来和对端建立连接,终会加入m_vecContInfo列表
139     //调用acceptex将accept socket绑定至完成端口,并开始进行事件监听
140     //这里需要传递Overlapped,new一个COverlappedIOInfo
141     //AcceptEx是m_listen的监听事件,m_listen已经绑定了完成端口;虽然ol->m_sSock已经创建,
142     //但未使用,现在不必为ol->m_sSock绑定完成端口。在AcceptEx事件发生后,再为ol->m_sSock绑定IOCP
143     DWORD byteReceived = 0;
144     if (FALSE == m_lpfnAcceptEx(
145         m_sListen,
146         ol->m_sSock,
147         ol->m_recvBuf.buf,
148         ol->m_recvBuf.len - (sizeof(SOCKADDR_IN)+16)*2,
149         sizeof(SOCKADDR_IN)+16,
150         sizeof(SOCKADDR_IN)+16,
151         &byteReceived,
152         ol))
153     {
154         DWORD res = WSAGetLastError();
155         if (ERROR_IO_PENDING != res)
156         {
157             cout<<"AcceptEx error , error code "<<res<<endl;
158             return false;
159         }
160     }
161     std::vector<SOCKET>::iterator iter = m_vecAcps.begin();
162     for (;iter != m_vecAcps.end(); iter++)
163     {
164         if (*iter == s)
165         {
166             *iter = ol->m_sSock;
167         }
168     }
169     if (iter == m_vecAcps.end())
170     {
171         m_vecAcps.push_back(ol->m_sSock);
172     }
173     return true;
174 }
175
176 bool CServer::DoAccept(COverlappedIOInfo* ol,DWORD NumberOfBytes)
177 {
178     //分支用于获取远端地址。
179     //如果接收TYPE_ACP同时收到第一帧数据,则第一帧数据内包含远端地址。
180     //如果没有收到第一帧数据,则通过getpeername获取远端地址
181     if (NumberOfBytes > 0)
182     {
183         //接受的数据分成3部分,第1部分是客户端发来的数据,第2部分是本地地址,第3部分是远端地址。
184         if (m_lpfnGetAcceptSockAddrs)
185         {
186             SOCKADDR_IN* ClientAddr = NULL;
187             SOCKADDR_IN* LocalAddr = NULL;
188             int remoteLen = sizeof(SOCKADDR_IN), localLen = sizeof(SOCKADDR_IN);
189             m_lpfnGetAcceptSockAddrs(
190                 ol->m_recvBuf.buf,
191                 ol->m_recvBuf.len - (sizeof(SOCKADDR_IN)+16)*2,
192                 sizeof(SOCKADDR_IN)+16,
193                 sizeof(SOCKADDR_IN)+16,
194                 (LPSOCKADDR*)&LocalAddr,
195                 &localLen,
196                 (LPSOCKADDR*)&ClientAddr,
197                 &remoteLen);
198             cout<<"收到新的连接请求,ip="<<inet_ntoa(ClientAddr->sin_addr)<<",port="<<ClientAddr->sin_port<<endl;
199             COverlappedIOInfo* pol = new COverlappedIOInfo;
200             pol->m_sSock = ol->m_sSock;
201             pol->m_addr =  *ClientAddr;
202             //服务端只收取recv,同时监听recv和send可用设计位偏移,用或运算实现
203             if (m_iocp.AssociateSocket(pol->m_sSock,TYPE_RECV))
204             {
205                 PostRecv(pol);
206
207                 m_vecContInfo.push_back(pol);
208             }
209             else
210             {
211                 delete pol;
212                 return false;
213             }
214         }
215     }
216     else if (NumberOfBytes==0)
217     {
218         //未收到第一帧数据
219     }
220     return true;
221 }
222
223 bool CServer::DoRecv(COverlappedIOInfo* ol)
224 {
225     cout<<"收到客户端数据:ip="<<inet_ntoa(ol->m_addr.sin_addr)<<",port="<<ol->m_addr.sin_port<<
226         ";内容="<<ol->m_recvBuf.buf<<endl;
227     return true;
228 }
229
230 bool CServer::PostRecv(COverlappedIOInfo* ol)
231 {
232     DWORD BytesRecvd = 0;
233     DWORD dwFlags = 0;
234     ol->ResetOverlapped();
235     ol->ResetRecvBuffer();
236     int recvnum = WSARecv(ol->m_sSock,&ol->m_recvBuf,1,&BytesRecvd,&dwFlags,(OVERLAPPED*)ol,NULL);
237     if (recvnum != 0)
238     {
239         int res = WSAGetLastError();
240         if (WSA_IO_PENDING != res)
241         {
242             cout<<"WSARecv error,error code "<<res<<endl;
243         }
244     }
245     return true;
246 }
247
248 UINT CServer::StartThreadPull()
249 {
250     //获取系统cpu个数启动线程
251     SYSTEM_INFO si;
252     GetSystemInfo(&si);
253     //启动cpu数量*2个线程
254     return Activate(si.dwNumberOfProcessors * 2);
255 }
256
257 bool CServer::DeleteLink(SOCKET s)
258 {
259     m_lsc.lock();
260     std::vector<COverlappedIOInfo*>::iterator iter = m_vecContInfo.begin();
261     for (;iter!=m_vecContInfo.end();iter++)
262     {
263         if (s == (*iter)->m_sSock)
264         {
265             COverlappedIOInfo* ol = *iter;
266             closesocket(s);
267             m_vecContInfo.erase(iter);
268             delete ol;
269             break;
270         }
271     }
272     m_lsc.unlock();
273     return true;
274 }
275
276 void CServer::svc()
277 {
278     while (true)
279     {
280         DWORD  NumberOfBytes = 0;
281         unsigned long CompletionKey = 0;
282         OVERLAPPED*    ol = NULL;
283         if (FALSE != GetQueuedCompletionStatus(m_iocp.GetIOCP(),&NumberOfBytes,&CompletionKey,&ol,WSA_INFINITE))
284         {
285             if (CompletionKey == TYPE_CLOSE)
286             {
287                 break;
288             }
289             COverlappedIOInfo* olinfo = (COverlappedIOInfo*)ol;
290             if (CompletionKey == TYPE_ACP)
291             {
292                 DoAccept(olinfo,NumberOfBytes);
293                 PostAccept(olinfo);
294             }
295             else if(CompletionKey == TYPE_RECV)
296             {
297                 if (NumberOfBytes == 0)
298                 {
299                     //客户端断开连接
300                     cout<<"客户端断开连接,ip="<<inet_ntoa(olinfo->m_addr.sin_addr)<<",port="<<olinfo->m_addr.sin_port<<endl;
301                     DeleteLink(olinfo->m_sSock);
302                     continue;
303                 }
304                 DoRecv(olinfo);
305                 PostRecv(olinfo);
306             }
307         }
308         else
309         {
310             cout<<"workthread GetQueuedCompletionStatus error,error code "<<WSAGetLastError()<<endl;
311             break;
312         }
313     }
314     cout<<"workthread stop"<<endl;
315 }
316
317 void CServer::CloseServer()
318 {
319     //1:清空IOCP线程队列,退出线程,有多少个线程发送多少个PostQueuedCompletionStatus信息
320     int threadnum = GetThreadsNum();
321     for (int i=0;i<threadnum;i++)
322     {
323         if (FALSE == m_iocp.PostStatus(TYPE_CLOSE))
324         {
325             cout<<"PostQueuedCompletionStatus error,error code "<<WSAGetLastError()<<endl;
326         }
327     }
328     //2:清空等待accept的套接字m_vecAcps
329     std::vector<SOCKET>::iterator iter = m_vecAcps.begin();
330     for (;iter != m_vecAcps.end();iter++)
331     {
332         SOCKET s = *iter;
333         closesocket(s);
334     }
335     m_vecAcps.clear();
336     //3:清空已连接的套接字m_vecContInfo并清空缓存
337     std::vector<COverlappedIOInfo*>::iterator iter2 = m_vecContInfo.begin();
338     for (;iter2 != m_vecContInfo.end();iter2++)
339     {
340         COverlappedIOInfo* ol = *iter2;
341         closesocket(ol->m_sSock);
342         iter2 = m_vecContInfo.erase(iter2);
343         delete ol;
344     }
345     m_vecContInfo.clear();
346 }

调用方法,控制台程序main函数内加入

1 SERVER::Instance()->StartListen(8828,"127.0.0.1");
2 int outId;
3 cin>>outId;
4 if (outId == 0)
5 {
6     SERVER::Close();
7 }

输入0结束服务程序。

测试结果1,接收数据

测试结果2,客户端断开连接

  

  机子比较垃圾,开1000个线程占用20多的CPU。有条件的可以多测试一些。

时间: 2024-11-05 11:29:30

winsock编程IOCP模型实现代码的相关文章

winsock编程WSAEventSelect模型

winsock编程WSAEventSelect模型 WSAEventSelect模型和WSAAsyncSelec模型类似,都是用调用WSAXXXXXSelec函数将socket和事件关联并注册到系统,并将socket设置成非阻塞模式.二者不同之处在于socket事件的通知方法:WSAAsyncSelec模型利用窗口句柄和消息映射函数通知网络事件,而WSAEventSelect模型利用WSAEVENT通知网络事件.完成WSAEventSelect模型需要涉及以下函数或结构: 1:WSAEventS

Winsock完成端口模型-Delphi代码

原文出处 <Windows网络编程技术>第8章 完成端口模型 由于原书附的是C代码,我把其翻译成Delphi代码. 其中winsock2.pas在delphi中不带,要另外下载http://jungla.dit.upm.es/~bti/files/winsock2.pas program CompletionIO; {$APPTYPE CONSOLE} uses  SysUtils,  WinSock2 in 'WinSock2.pas',  Mains in 'Mains.pas'; beg

对于TCP协议中IOCP模型的一些简单的理解

请不要觉得这一篇没有代码的文章没意义,对IOCP模型的代码,百度搜索可以得到很多,但是后续很多需要纠结的地方,很多人都经历过,如果你已经在尝试写IOCP服务端了,那么你很可能会对写代码之外的一些设计问题很纠结,那么本文很可能是对你有所帮助的,这一个帖子是我开的讨论帖,我不是很懂CSDN的帖子分数的意义,我觉得那对于我这种1年难得发1贴的人来说估计也没什么作用,但我很希望大家能一起参与进来讨论:http://bbs.csdn.net/topics/390890567?page=1#post-398

IOCP模型与网络编程

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

IOCP模型与网络编

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

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)与一个完成端口关联了起来,当一个网络事件发生的时

基于UDP的Winsock编程(C++版)

基于UDP的Winsock编程与基于TCP的Winsock编程相比,只是缺少了一个步骤而已.对于Server,缺少了接受连接的过程(accept()函数调用):对于Client,缺少了请求连接的过程(connect()函数调用). 另外与TCP区别的还有,在UDP中,数据收发函数是:sendto(),和recvfrom()函数. 函数原型为: int sendto(SOCKET s,const char FAR *buf,int len,int flags,const struct sockad

Winsock 编程流程

最近看了<Window程序设计>感觉在网络方面讲的不错,讲的很通俗易懂,与大家一同交流 转载请注明出处:http://blog.csdn.net/u010484477谢谢^_^ 使用 Winsock 编程的一般步骤是比较固定的. 1.Winsock 库的装入.初始化和释放 所有的 WinSock 函数都是从 WS2_32.DLL 库导出的,VC++在默认情况下并没有连接到该库,如果想使用 Winsock API,就必须包含相应的库文件. #pragma commment(lib, "