1
2
3
4
|
//初始化套接字库
WSADATA
wsaData;
WSAStartup(MAKEWORD(2,2),
&wsaData );
|
1
2
3
4
5
|
//创建IOCP句柄
HANDLE
m_hIocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE,0,0,0);
//创建服务器套接字,这里要注意的是最后一个参数必须为:WSA_FLAG_OVERLAPPED
重叠模式
SOCKET
m_Server = WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
|
1
2
3
4
5
|
SOCKADDR_IN
addr;
addr.sin_addr.S_un.S_addr
= inet_addr( "127.0.0.1" );
addr.sin_family
= AF_INET;
addr.sin_port
= htons(2000);
bind(m_Server,(SOCKADDR*)&addr, sizeof (SOCKADDR);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
//
监听线程流程
UINT
WINAPI AcceptThreadProc( LPVOID
lpParameter ){
sockaddr_in
sockAddr = {0};
int
len = sizeof (sockAddr);
while (TRUE){
SOCKET
sNew = WSAAccept(m_Server,(sockaddr*)&sockAddr,&len,NULL,NULL);
//
将客户端加入到IOCP队列中
CreateIoCompletionPort(( HANDLE )sNew,m_hIocp, ULONG_PTR (sNew),0);
//
这里要注意一下,对网上一些相关的资料,一些新手在写IOCP时
//
会发现得不到用户请求及一些事件,哪是因为没有对该用户投递一个接收IO
//
IOCP的工作原理就是,必须对一个连接投递一个投收IO,处理完一个,再投递一个...
OVERLAPPEDPLUS*
ol; //
....对OL结构进行初始化后
int
nRet = WSARecv(ol->s, &(ol->wsaBuf), 1, &(ol->dwBytes), &(ol->dwFlags), &(ol->ol), NULL);
int
nError = WSAGetLastError();
//
在投递接收IO时。返回值要注意。如果为 nError == ERROR_IO_PENDING 说明已经投递成功。
}}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
//
工作线程流程
UINT
WINAPI WorkerThreadProc( LPVOID
lpParameter )
{
DWORD
CompleteBytes
= 0;
DWORD
dwKey
= 0;
POVERLAPPEDPLUS
ol = NULL;
BOOL
bRet = GetQueuedCompletionStatus(m_hIocp,&CompleteBytes,( PULONG_PTR )&dwKey,(LPOVERLAPPED*)&ol,INFINITE);
if (!bRet)
{
//
客户端断开了连接
}
//
如果为接收时 CompleteBytes 为实际收到的大,发送时为实际发送的大小
switch (ol->OpCode)
{
case
IOCP_RECV:
//....
处理接收请求
break ;
case
IOCP_SEND:
//....
处理发送请求
break ;
}
}
|