学习的时候,在网上找了好久,但是都没找到满意的。自己会了,写一个可以运行的吧!
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;
- //
- <span style="color:#FF0000;">memset(&pPer_IO_Data->overlapped,0,sizeof(pPer_IO_Data->overlapped));</span>
- //投递一个接收请求
- ::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;
- }