下面是用完成端口写的一个简单的 例子, 完成端口和重叠io 一样都是异步io。
代码如下。欢迎大家建议 改进、
#pragma comment(lib, "ws2_32")
#include <windows.h>
#include <WINSOCK2.H>
#include <process.h>
#define SERVER_PORT 4567
#define READ 1
#define WRITE 2
//存储客户端信息
typedef struct
{
SOCKET s_client;
sockaddr_in client_address;
}CLIENT, *PCLIENT;
//获取io的信息
typedef struct
{
OVERLAPPED ol;
char recv_data[100];
int op;
}IO_RECV, *P_IORECV;
bool InitVersion()
{
WSADATA data;
unsigned int sock_version = MAKEWORD(2, 2);
if (::WSAStartup(sock_version, &data) != 0)
{
return false;
}
else
return true;
}
void release_version()
{
::WSACleanup();
}
static HANDLE g_completion = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
//处理客户端的请求
unsigned int __stdcall deal_client(void *p)
{
P_IORECV temp_overlapped;
PCLIENT temp_client;
DWORD trans_len;
while(1)
{
BOOL b = ::GetQueuedCompletionStatus(g_completion, &trans_len, (unsigned long *)&temp_client, (OVERLAPPED * *)&temp_overlapped, WSA_INFINITE);
if (b)
{
OutputDebugString("读取数据\n");
if (temp_overlapped->op == READ)
{
temp_overlapped->recv_data[trans_len] = 0;
printf("%s\n======", temp_overlapped->recv_data);
WSABUF buf;
buf.buf = temp_overlapped->recv_data;
buf.len = 100;
DWORD dwRecv;
DWORD flg = 0;
temp_overlapped->op = READ;
::WSARecv(temp_client->s_client, &buf, 1, &trans_len, &flg, &temp_overlapped->ol, NULL);
printf("%d", WSAGetLastError ());
}
}
}
return 0;
}
//将客户端的套接字 关联到完成端口
void associated_socket(const SOCKET & s, const sockaddr_in & client_address)
{
PCLIENT client = (PCLIENT)::GlobalAlloc(GPTR, sizeof(CLIENT));
client->s_client = s;
client->client_address = client_address;
::CreateIoCompletionPort((HANDLE)client->s_client, g_completion, (DWORD)client, 0);
}
//发送一个异步的读操作
void asyn_read_message(const SOCKET & s)
{
P_IORECV p_read = (P_IORECV)::GlobalAlloc(GPTR, sizeof(IO_RECV));;
p_read->op = READ;
WSABUF buf;
buf.buf = p_read->recv_data;
buf.len = 100;
DWORD dwRecv;
DWORD flg = 0;
::WSARecv(s, &buf, 1, &dwRecv, &flg, &p_read->ol, NULL);
}
int main(int argc, char* argv[])
{
InitVersion();
SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in s_ip;
s_ip.sin_family = AF_INET;
s_ip.sin_port = ::ntohs(4567);
s_ip.sin_addr.S_un.S_addr = INADDR_ANY;
::bind(sListen, (sockaddr *)&s_ip, sizeof(s_ip));
::listen(sListen, 5);
_beginthreadex(NULL, 0, deal_client, (void *)g_completion, 0, 0);
while(1)
{
sockaddr_in client_address;
int len = sizeof(client_address);
SOCKET s_client = ::accept(sListen, (sockaddr *)&client_address, &len);
//将客户端socket关联到 完成端口
associated_socket(s_client, client_address);
//对客户端套接字 发送异步的读操作
asyn_read_message(s_client);
}
release_version();
return 0;
}