学习的时候,在网上找了好久,但是都没找到满意的。自己会了,写一个可以运行的吧!
memset(&pPer_IO_Data->overlapped,0,sizeof(pPer_IO_Data->overlapped));
这一句非常重要,因为开始几次没有写这句话,老是出现问题,而且还找不到原因,查了好多的资料,总算是解决了!!
也希望大家能避免这个问题!
#include <WINSOCK2.H>
#include <windows.h>
#include <iostream>
#include <basetsd.h>
using namespace std;
#pragma comment(lib,"ws2_32.lib")
#define BUFFER_SIZE 4096
#define PORT 12345
#define OP_READ 1
#define OP_WRITE 2
#define OP_ACCEPT 3
static int index=0;
HANDLE hCompletion;
typedef struct _PER_HANDLE_DATA
{
SOCKET sock;
sockaddr_in si;
}PER_HANDLE_DATA,*PPER_HANDLE_DATA;
typedef struct _PER_IO_DATA
{
OVERLAPPED overlapped;
WSABUF wsabuf;
char buffer[BUFFER_SIZE];
int operationType;
}PER_IO_DATA,*PPER_IO_DATA;
DWORD WINAPI ServerThread(LPVOID lParam);
int main()
{
WSADATA wsa;
WSAStartup(MAKEWORD(2,2),&wsa);
hCompletion=::CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
HANDLE h_DoThread=CreateThread(NULL,0,ServerThread,(LPVOID)hCompletion,0,0);
SOCKET sListen=socket(AF_INET,SOCK_STREAM,0);
sockaddr_in si;
si.sin_family=AF_INET;
si.sin_port=htons(PORT);
si.sin_addr.S_un.S_addr=INADDR_ANY;
bind(sListen,(SOCKADDR *)&si,sizeof(SOCKADDR));
listen(sListen,5);
while(TRUE)
{
sockaddr_in RemoteInfo;
int RemoteLen=sizeof(sockaddr_in);
SOCKET AcceptClient=accept(sListen,(sockaddr*)&RemoteInfo,&RemoteLen);
//每当有新连接时,将为其创建PER_HANDLE_DATA数据和PER_IO_DATA数据。
//PER_HANDLE_DATA
PPER_HANDLE_DATA pPerHandleData=new PER_HANDLE_DATA();
pPerHandleData->sock=AcceptClient;
memcpy(&(pPerHandleData->si),&RemoteInfo,sizeof(sockaddr));
//将套接字句柄与完成端口相关联
CreateIoCompletionPort((HANDLE)pPerHandleData->sock,hCompletion,
(DWORD)pPerHandleData,0);
//PER_IO_DATA
PPER_IO_DATA pPer_IO_Data=new PER_IO_DATA();
pPer_IO_Data->operationType=OP_READ;
//WSARecv等函数中,缓冲区必须是WSABUF,下面对WSABUF进行初始化
pPer_IO_Data->wsabuf.buf=pPer_IO_Data->buffer;
pPer_IO_Data->wsabuf.len=BUFFER_SIZE;
DWORD dwRecv;
DWORD dwFlags=0;
//
memset(&pPer_IO_Data->overlapped,0,sizeof(pPer_IO_Data->overlapped));
//投递一个接收请求
::WSARecv(pPerHandleData->sock,&(pPer_IO_Data->wsabuf),
1,&dwRecv,&dwFlags,&(pPer_IO_Data->overlapped),NULL);
}
return 0;
}
DWORD WINAPI ServerThread(LPVOID lParam)
{
HANDLE hCompletion=(HANDLE)lParam;
DWORD dwTrans;
PPER_HANDLE_DATA pPer_Handle_Data;
PPER_IO_DATA pPer_IO_Data;
cout<<"ServerThread"<<endl;
while (TRUE)
{
bool bOk=GetQueuedCompletionStatus(hCompletion,&dwTrans,(LPDWORD)&pPer_Handle_Data,(LPOVERLAPPED*)&pPer_IO_Data,INFINITE);
if(!bOk)
{
cout<<GetLastError()<<endl;
//在此套接字上有错误发生
closesocket(pPer_Handle_Data->sock);
delete pPer_Handle_Data;
delete pPer_IO_Data;
continue;
}
//套接字被对方关闭
if(dwTrans==0 && pPer_IO_Data->operationType==OP_READ || pPer_IO_Data->operationType==OP_WRITE )
{
closesocket(pPer_Handle_Data->sock);
delete pPer_Handle_Data;
delete pPer_IO_Data;
continue;
}
switch(pPer_IO_Data->operationType)
{
cout<<"Switch"<<endl;
case OP_READ:
{
pPer_IO_Data->buffer[dwTrans]='\0';
cout<<pPer_IO_Data->buffer<<endl;
index++;
cout<<index<<endl;
//继续投递IO操作
WSABUF wsabuf;
wsabuf.buf=pPer_IO_Data->buffer;
wsabuf.len=BUFFER_SIZE;
pPer_IO_Data->operationType=OP_READ;
DWORD flags=0;
WSARecv(pPer_Handle_Data->sock,&wsabuf,1,&dwTrans,&flags,&(pPer_IO_Data->overlapped),NULL);
}
case OP_WRITE:
break;
case OP_ACCEPT:
break;
}
}
return 0;
}