一个简单的聊天服务器程序(学winsocket的新人机会难得哦!!)
这是本人用WSAEventSelect()来写的一个I/O异步的模式,发送方式采用流试数据TCP的形式;程序代码:
#include "stdafx.h" #include <winsock2.h> #pragma comment(lib,"ws2_32.lib") #define WSA_MAXIMUM_EVENTS 60 void RecvData(SOCKET s, char buffer[], int size); void SendData(SOCKET s, SOCKET a[], DWORD size, char buffer[], int str); int _tmain(int argc, _TCHAR* argv[]) { WSADATA wsd; SOCKET Socket[WSA_MAXIMUM_EVENTS]; //建立60个套接字 WSAEVENT Event[WSA_MAXIMUM_EVENTS]; //建立60个事件对象句柄 WSANETWORKEVENTS NetworkEvents; //网络事件类型结构 WSAEVENT NewEvent; //事件对象句柄 struct sockaddr_in local; //网络信息结构 SOCKET Accept,Listen; //套接字句柄 DWORD EventTotal = 0; //事件计数 DWORD Index,i; //事件句柄引索 char buffer[1024]; local.sin_family = AF_INET; local.sin_addr.S_un.S_addr = inet_addr("192.168.0.100"); local.sin_port = htons(5150); if(WSAStartup(MAKEWORD(2,2),&wsd) != 0) { printf("add winsocket to failed\n"); getchar(); return 0; } Listen = socket(PF_INET,SOCK_STREAM,0); if(Listen == SOCKET_ERROR) { printf("socket to error!!!\n"); getchar(); return 0; } if(bind(Listen,(PSOCKADDR) &local, sizeof(local)) == SOCKET_ERROR) { printf("bind to error!!!\n"); getchar(); return 0; } NewEvent = WSACreateEvent(); WSAEventSelect(Listen,NewEvent,FD_ACCEPT | FD_CLOSE); listen(Listen,60); Socket[EventTotal] = Listen; Event[EventTotal] = NewEvent; EventTotal++; while(TRUE) { Index = WSAWaitForMultipleEvents(EventTotal,Event,FALSE,WSA_INFINITE,FALSE); WSAEnumNetworkEvents( Socket[Index - WSA_WAIT_EVENT_0],Event[Index - WSA_WAIT_EVENT_0],&NetworkEvents); if(NetworkEvents.lNetworkEvents & FD_ACCEPT) { if(NetworkEvents.iErrorCode[FD_ACCEPT_BIT] != 0) { printf("FD_ACCEPT failed with error %d\n",NetworkEvents.iErrorCode[FD_ACCEPT_BIT]); getchar(); // break; } Accept = accept(Socket[Index - WSA_WAIT_EVENT_0],NULL,NULL); if(EventTotal > WSA_MAXIMUM_WAIT_EVENTS) { printf("Too many connections\n"); closesocket(Accept); getchar(); //break; } NewEvent = WSACreateEvent(); WSAEventSelect(Accept,NewEvent,FD_READ | FD_CLOSE); Event[EventTotal] = NewEvent; Socket[EventTotal] = Accept; EventTotal++; printf("Socket %d connected\n",Accept); } if(NetworkEvents.lNetworkEvents & FD_READ) { if(NetworkEvents.iErrorCode[FD_READ_BIT] != 0) { printf("FD_READ failed with error %d\n",NetworkEvents.iErrorCode[FD_READ_BIT]); //getchar(); //break; } else { //printf("read data to:"); RecvData(Socket[Index - WSA_WAIT_EVENT_0],buffer,1024); i = *(int*)buffer; printf("\n%d号准备发送%d个字节\n",Index - WSA_WAIT_EVENT_0,i); if(buffer[4]) SendData(Socket[Index - WSA_WAIT_EVENT_0],Socket,EventTotal,buffer,i); } } if(NetworkEvents.lNetworkEvents & FD_CLOSE) { if(NetworkEvents.iErrorCode[FD_CLOSE_BIT] != 0) { printf("FD_READ failed with error %d\n",NetworkEvents.iErrorCode[FD_CLOSE_BIT]); getchar(); //break; } closesocket(Socket[Index - WSA_WAIT_EVENT_0]); WSACloseEvent(Event[Index - WSA_WAIT_EVENT_0]); printf("COLSE SOCKET..................\n"); for(i = Index - WSA_WAIT_EVENT_0; i < (int) EventTotal; i++) { Socket[i] = Socket[i + 1]; Event[i] = Event[i + 1]; } EventTotal--; } } closesocket(Listen); WSACleanup(); return 0; } void RecvData(SOCKET s, char buffer[], int size) { int i,Index,Length; Length = i = 0; do { Index = recv(s,&buffer[Length],size,0); if(Index == SOCKET_ERROR) { buffer[4] = 0; break; } if(Index > 4 && i == 0) { i = *((int*) buffer); printf("接收%d字节数据\n",i); } Length += Index; if(Length > 1024) { printf("已超出接收范围数据\n"); break; } }while(Length < i); buffer[Length] = 0; printf("接收字符串:%s",&buffer[4]); } void SendData(SOCKET s, SOCKET a[], DWORD size, char buffer[], int str) { DWORD i; int Index,l,ret; printf("共有%d组套节字\n",size); for(i = 1; i < size; i++) { if(a[i] != s) { printf("开始发给%d套节字\n",a[i]); l = str; Index = 0; printf("sending....."); do { ret = send(a[i],&buffer[Index],str,0); if(ret == SOCKET_ERROR) { printf("send to fialed\n"); break; } l -= ret; Index += ret; printf("...."); }while(l > 0); printf("\n"); } } }