server :
#define RECV_POSTED 0
#define SEND_POSTED 1
char Buffer[1024];
typedef struct _PER_HANDLE_DATA
{
SOCKET Socket; //该结构是用于向端口传送套接字的
}PER_HANDLE_DATA,*LPER_HANDLE_DATA;
typedef struct _PER_IO_DATA
{
OVERLAPPED Overlapped;
WSABUF WsaBuffer;
DWORD RecvByte,SendByte;
int OperationType;
}PER_IO_DATA,*LPER_IO_DATA;
//*********************************************************************************
// ServerWorkThread............
//*********************************************************************************
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
HANDLE CompletionPort =(HANDLE)CompletionPortID;
DWORD BytesTransferred;
PER_IO_DATA PerIoData;
PER_HANDLE_DATA PerHandleData;
DWORD Flags;
WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS];
DWORD totalEvent=0;
DWORD indexEvent;
while(TRUE)
{
if(GetQueuedCompletionStatus(CompletionPort,&BytesTransferred,
(LPDWORD)&PerHandleData,(LPOVERLAPPED*)&PerIoData,INFINITE)==NULL)
{
printf("wait error...errorcode:%d",WSAGetLastError());
//等待失败!错误:WSAGetLastError()
continue;
}
//did not use WSAEvent..................
/* if(BytesTransferred==0 &&(PerIoData->OperationType==RECV_POSTED
||PerIoData->OperationType==SEND_POSTED))
{
cout<<"套接字已经关闭!"<<endl;
closesocket(PerHandleData.Socket);
GlobalFree(PerHandleData);
continue;
}
*/
EventArray[totalEvent] = WSACreateEvent();
ZeroMemory(&PerIoData.Overlapped,sizeof(OVERLAPPED));
PerIoData.WsaBuffer.buf =Buffer;
PerIoData.WsaBuffer.len =2048;
PerIoData.Overlapped.hEvent=EventArray[totalEvent];
PerIoData.OperationType =RECV_POSTED;
indexEvent = WSAWaitForMultipleEvents(totalEvent, EventArray, FALSE, WSA_INFINITE, FALSE);
WSAResetEvent(EventArray[indexEvent - WSA_WAIT_EVENT_0]);
//-----------------------------------------
// Determine the status of the overlapped event
WSAGetOverlappedResult(PerHandleData.Socket,&PerIoData.Overlapped, &BytesTransferred, FALSE, &Flags);
if (BytesTransferred == 0) {
printf("Closing Socket %d/n", PerHandleData.Socket);
closesocket(PerHandleData.Socket);
WSACloseEvent(EventArray[indexEvent - WSA_WAIT_EVENT_0]);
return 0;
}
if(PerIoData.OperationType==RECV_POSTED)
{
printf("Recved things is :%s/n",PerIoData.WsaBuffer.buf);
// 接收到的数据
}
//继续接收数据...
printf("go on recving........../n");
if(WSARecv(PerHandleData.Socket,&(PerIoData.WsaBuffer),1,&(PerIoData.RecvByte),&Flags,&(PerIoData.Overlapped),NULL)==SOCKET_ERROR)
{
//发送数据失败...
printf("send error ..errorcode is:%d/n",WSAGetLastError());
continue;
}
}
}
//*********************************************************************************
void main()
{
HANDLE CompletionPort;
WSADATA WsaData;
SYSTEM_INFO SystemInfo;
SOCKADDR_IN ServerAddr;
SOCKADDR_IN ClientAddr;
int ClientAddrLen;
SOCKET ListenSocket;
SOCKET NewSocket;
PER_HANDLE_DATA PerHandleData;//*PerHandleData=NULL;
PER_IO_DATA PerIoData;//*PerIoData;
DWORD Flags=NULL;
if(WSAStartup(MAKEWORD(2,2),&WsaData)!=NULL) //winsock2
{
printf("注册失败!错误是:%d/n",WSAGetLastError());
ExitProcess(1);
}
ListenSocket=WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
if(ListenSocket==INVALID_SOCKET)
{
printf("套接字创建失败!/n");
WSACleanup();
ExitProcess(1);
}
//******************************************************************************************
CompletionPort=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
if(CompletionPort==INVALID_HANDLE_VALUE)
{
printf("创建端口对象错误!/n");
WSACleanup();
ExitProcess(1);
}
GetSystemInfo(&SystemInfo); //获得系统的information
printf("the CPU's num is :%d/n",SystemInfo.dwNumberOfProcessors);
for(DWORD i=0;i< SystemInfo.dwNumberOfProcessors;i++) //创建工作器线程的数量是处理器的 2 倍加 2 个
{
HANDLE ThreadHandle;
ThreadHandle=CreateThread(NULL,0,ServerWorkerThread,CompletionPort,0,NULL);
CloseHandle(ThreadHandle);
}
//bind with server===================================================
ServerAddr.sin_family =AF_INET;
ServerAddr.sin_addr.s_addr =htonl(INADDR_ANY);
ServerAddr.sin_port =htons(8000);
if(bind(ListenSocket,(PSOCKADDR)&ServerAddr,sizeof(ServerAddr))==SOCKET_ERROR)
{
printf("套接字绑定错误:%d/n",WSAGetLastError());
WSACleanup();
ExitProcess(1);
}
if(listen(ListenSocket,5)==SOCKET_ERROR)
{
//套接字监听失败!
printf("listen error ....:%d",WSAGetLastError());
WSACleanup();
ExitProcess(1);
}
ClientAddrLen=sizeof(ClientAddr);
while(TRUE)
{
printf("listening begin................./n");
NewSocket=WSAAccept(ListenSocket,(SOCKADDR*)&ClientAddr,&ClientAddrLen,NULL,0);//client_info
if(NewSocket==INVALID_SOCKET)
{
printf("accept error........./n");
continue;
}
//PerHandleData=(LPER_HANDLE_DATA)GlobalAlloc(GPTR,sizeof(PER_HANDLE_DATA));//用globalalloc分配一块
//固定的内存,并初始为0
printf("收到端口号 %d,地址是%s 的链接!/n",ntohs(ClientAddr.sin_port),
inet_ntoa(ClientAddr.sin_addr));
PerHandleData.Socket = NewSocket;
//PerHandleData->Socket=NewSocket;
// memcpy(&PerHandleData->ClientAddr,&ClientAddr,ClientAddrLen);
//PerHandleData是用于保存用户的SOCKET信息的
CreateIoCompletionPort((HANDLE)NewSocket,CompletionPort,(DWORD)&PerHandleData,0);
// 完成端口同套接字关联起来
//PerIoData =(LPER_IO_DATA)GlobalAlloc(GPTR,sizeof(PER_IO_DATA));
PerIoData.WsaBuffer.buf =Buffer;
PerIoData.WsaBuffer.len =sizeof(Buffer);
PerIoData.OperationType =RECV_POSTED;
ZeroMemory(&PerIoData.Overlapped,sizeof(PerIoData.Overlapped));
if(WSARecv(NewSocket,&PerIoData.WsaBuffer,1,&PerIoData.RecvByte,&Flags,&(PerIoData.Overlapped),NULL)==SOCKET_ERROR)
{
printf("接收数据失败!错误:%d",WSAGetLastError());
continue;
}
}
printf("server is closed..../n");
closesocket(NewSocket);
WSACleanup();
}
.....
client :
#define NO_FLAGS_SET 0
#pragma comment(lib,"ws2_32.lib")
#define PORT (u_short) 8000
#define DEST_IP_ADDR "127.0.0.1" //Server address
int main(void)
{
WSADATA Data;
SOCKADDR_IN destSockAddr;
SOCKET destSocket;
unsigned long destAddr;
int status;
int numsnt;
char *toSendtxt="I am Coming............haha";
status=WSAStartup(MAKEWORD(1, 1), &Data);
if (status != 0)
printf("ERROR: WSAStartup unsuccessful/n");
/* convert IP address into in_addr form */
destAddr=inet_addr(DEST_IP_ADDR);
/* copy destAddr into sockaddr_in structure */
memcpy(&destSockAddr.sin_addr,
&destAddr, sizeof(destAddr));
/* specify the port portion of the address */
destSockAddr.sin_port=htons(PORT);
/* specify the address family as Internet */
destSockAddr.sin_family=AF_INET;
destSocket=socket(AF_INET, SOCK_STREAM, 0);
if (destSocket == INVALID_SOCKET)
{
printf("ERROR: socket unsuccessful/n");
status=WSACleanup();
if (status == SOCKET_ERROR)
printf("ERROR: WSACleanup unsuccessful/n");
return(1);
}
printf("Trying to connect to IP Address:%s",DEST_IP_ADDR);
/* connect to the server */
status=connect(destSocket,(LPSOCKADDR) &destSockAddr,sizeof(destSockAddr));
if (status == SOCKET_ERROR)
{
printf("ERROR: connect unsuccessful/n");
status=closesocket(destSocket);
if (status == SOCKET_ERROR)
printf("ERROR: closesocket unsuccessful");
status=WSACleanup();
if (status == SOCKET_ERROR)
printf("ERROR: WSACleanup unsuccessful");
return(1);
}
printf("Connected.../n" );
while(1)
{
printf("Sending.../n" );
numsnt=send(destSocket, toSendtxt,strlen(toSendtxt) + 1, NO_FLAGS_SET);
if (numsnt != (DWORD)strlen(toSendtxt) + 1)
{
printf("Connection terminated/n" );
status=closesocket(destSocket);
if (status == SOCKET_ERROR)
printf("ERROR: closesocket unsuccessful/n" );
status=WSACleanup();
if (status == SOCKET_ERROR)
printf("ERROR: WSACleanup unsuccessful/n" );
return(1);
}
/* Wait before sending the message again */
Sleep(4800);
} /* while */
}
遇到一SOCKET 10038无效SOCKET 错误,在网上查了好长时间,仍没能解决,大家指点啊。。。。
在WHILE 处,
为什么第一次收到数据正常,第二次就是SOCKET_ERROR 呢?