一个简单的聊天服务器程序(学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");
}
}
}








楼主