#include
"stdafx.h"
#include
<
iostream
.h>
#include
#include
#include
#define
PORT
5150
#define
DATA_BUFSIZE
8192
typedef
struct
{
OVERLAPPED
OVerlapped
;
WSABUF
DATABuf
;
CHAR
Buffer
[
DATA_BUFSIZE
];
DWORD
BytesSend
,
BytesRecv
;
}
PER_IO_OPERATION_DATA
, *
LPPER_IO_OPERATION_DATA
;
typedef
struct
{
SOCKET
Socket
;
}
PER_HANDLE_DATA
,*
LPPER_HANDLE_DATA
;
DWORD
WINAPI
ServerWorkerThread
(
LPVOID
ComlpetionPortID
);
int
main(
int
argc
,
char
*
argv
[])
{
SOCKADDR_IN
InternetAddr
;
SOCKET
Listen
,
Accept
;
HANDLE
CompetionPort
;
SYSTEM_INFO
SystenInfo
;
LPPER_HANDLE_DATA
PerHandleData
;
LPPER_IO_OPERATION_DATA
PerIOData
;
int
i
;
DWORD
RecvBytes
;
DWORD
Flags
;
DWORD
ThreadID
;
WSADATA
wsadata
;
DWORD
Ret
;
if
(
Ret
=
WSAStartup
(0x2020,&
wsadata
) != 0)
{
printf
(
"WSAStartup failed with error %d/n"
,
Ret
);
return
0;
}
//
打开一个空的完成端口
if
((
CompetionPort
=
CreateIoCompletionPort
(
INVALID_HANDLE_VALUE
,
NULL
,0,0)) ==
NULL
)
{
printf
(
"CreateIoCompletionPort failed with error %d/n"
,
GetLastError
());
return
0;
}
GetSystemInfo
(&
SystenInfo
);
//
开启
cpu
个数的
2
倍个的线程
for
(
i
=0;
i
<
SystenInfo
.
dwNumberOfProcessors
*2;
i
++)
{
HANDLE
ThreadHandle
;
//
创建服务器工作线程,并且向线程传送完成端口
if
((
ThreadHandle
=
CreateThread
(
NULL
,0,
ServerWorkerThread
,
CompetionPort
,0,&
ThreadID
)) ==
NULL
)
{
printf
(
"CreateThread failed with error %d/n"
,
GetLastError
());
return
0;
}
CloseHandle
(
ThreadHandle
);
}
//
打开一个服务器
socket
if
((
Listen
=
WSASocket
(
AF_INET
,
SOCK_STREAM
, 0,
NULL
, 0,
WSA_FLAG_OVERLAPPED
)) ==
INVALID_SOCKET
)
{
printf
(
"WSASocket() failed with error %d/n"
,
WSAGetLastError
());
return
0;
}
InternetAddr
.
sin_family
=
AF_INET
;
InternetAddr
.
sin_addr
.
S_un
.
S_addr
=
htonl
(
INADDR_ANY
);
InternetAddr
.
sin_port
=
htons
(
PORT
);
if
(
bind
(
Listen
,(LPSOCKADDR)&
InternetAddr
,
sizeof
(
InternetAddr
)) ==
SOCKET_ERROR
)
{
printf
(
"bind failed with error %d/n"
,
WSAGetLastError
());
return
0;
}
if
(
listen
(
Listen
,5) ==
SOCKET_ERROR
)
{
printf
(
"listen failed with error %d/n"
,
WSAGetLastError
());
return
0;
}
//
接收连接并且分发给完成端口
while
(
TRUE
)
{
if
((
Accept
=
WSAAccept
(
Listen
,
NULL
,
NULL
,
NULL
,0)) ==
SOCKET_ERROR
)
{
printf
(
"WSAAccept failed with error %d/n"
,
WSAGetLastError
());
return
0;
}
//
创建与套接字相关的套接字信息结构
if
((
PerHandleData
= (
LPPER_HANDLE_DATA
)
GlobalAlloc
(
GPTR
,
sizeof
(
PER_HANDLE_DATA
))) ==
NULL
)
{
printf
(
"GlobalAlloc failed with error %d/n"
,
GetLastError
());
return
0;
}
// Associate the accepted socket with the original completion port.
printf
(
"Socket number %d connected/n"
,
Accept
);
PerHandleData
->
Socket
=
Accept
;
//
结构中存入接收的套接字
//
与我们的创建的那个完成端口关联起来
,
将关键项也与指定的一个完成端口关联
if
((
CreateIoCompletionPort
((
HANDLE
)
Accept
,
CompetionPort
,(
DWORD
)
PerHandleData
,0)) ==
NULL
)
{
printf
(
"CreateIoCompletionPort failed with error%d/n"
,
GetLastError
());
return
0;
}
//
创建同下面的
WSARecv
调用相关的
IO
套接字信息结构体
if
((
PerIOData
= (
LPPER_IO_OPERATION_DATA
)
GlobalAlloc
(
GPTR
,
sizeof
(
PER_IO_OPERATION_DATA
))) =
NULL
)
{
printf
(
"GlobalAloc failed with error %d/n"
,
GetLastError
());
return
0;
}
ZeroMemory
(&(
PerIOData
->
OVerlapped
),
sizeof
(OVERLAPPED));
PerIOData
->
BytesRecv
= 0;
PerIOData
->
BytesSend
= 0;
PerIOData
->
DATABuf
.
len
=
DATA_BUFSIZE
;
PerIOData
->
DATABuf
.
buf
=
PerIOData
->
Buffer
;
Flags
= 0;
if
(
WSARecv
(
Accept
,&(
PerIOData
->
DATABuf
),1,&
RecvBytes
,&
Flags
,&(
PerIOData
->
OVerlapped
),
NULL
) ==
SOCKET_ERROR
)
{
if
(
WSAGetLastError
() !=
ERROR_IO_PENDING
)
{
printf
(
"WSARecv() failed with error %d/n"
,
WSAGetLastError
());
return
0;
}
}
}
return
0;
}