winsock select 学习代码(2)

之前文章的改进版

服务器仅仅接受客户端发送的字符串并显示

客户端可以调节发送数目 但是不能超过64

 

// SelectServer.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <winsock2.h>
#include <conio.h>

#pragma comment(lib,"ws2_32")

#define SOCKET_MAXCNT	64
#define THREAD_NUM		2 
#define CONNECT_PORT	8773	
#define CONNECT_ADDR	"127.0.0.1"
#define DATA_BUF_SZIE	8192

typedef struct _SOCKET_INFORMATION {
	CHAR Buffer[DATA_BUF_SZIE];
	WSABUF DataBuf;
	SOCKET Socket;
	OVERLAPPED Overlapped;
} SOCKET_INFORMATION, * LPSOCKET_INFORMATION;

DWORD	totalSockets = 0;
LPSOCKET_INFORMATION SocketArray[FD_SETSIZE];


BOOL CreateSocketInformation(SOCKET s)
{
	LPSOCKET_INFORMATION SI;

	printf("Accepted socket number %d\n", s);

	if ((SI = (LPSOCKET_INFORMATION) GlobalAlloc(GPTR,
		sizeof(SOCKET_INFORMATION))) == NULL)
	{
		printf("GlobalAlloc() failed with error %d\n", GetLastError());
		return FALSE;
	}

	// Prepare SocketInfo structure for use.

	SI->Socket = s;

	SocketArray[totalSockets] = SI;

	totalSockets++;

	return(TRUE);
}


void FreeSocketInformation(DWORD Index)
{
	LPSOCKET_INFORMATION SI = SocketArray[Index];
	DWORD i;

	closesocket(SI->Socket);

	printf("Closing socket number %d\n", SI->Socket);

	GlobalFree(SI);

	// Squash the socket array

	for (i = Index; i < totalSockets; i++)
	{
		SocketArray[i] = SocketArray[i + 1];
	}

	totalSockets--;
}


int _tmain(int argc, _TCHAR* argv[])
{
	WSAData	wsaData;
	SOCKADDR_IN InternetAddr = {0};
	FD_SET ReadSet;
	DWORD	i = 0;
	DWORD	total = 0;
	DWORD	Flags;
	DWORD	RecvBytes = 0;
	SOCKET	listenSock = INVALID_SOCKET;
	SOCKET  acceptSock = INVALID_SOCKET;
	if( WSAStartup(MAKEWORD(2,2),&wsaData) != 0 )
	{
		printf("WSAStartup error,exit\n");
		goto SOCKET_CLEAN;
	}

	listenSock = WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,
		WSA_FLAG_OVERLAPPED);
	if(listenSock == INVALID_SOCKET)
	{
		printf("WSASocket error \n");
		goto SOCKET_CLEAN;
	}

	InternetAddr.sin_family = AF_INET;
	InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	InternetAddr.sin_port = htons(CONNECT_PORT);

	if (bind(listenSock, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr))
		== SOCKET_ERROR)
	{
		printf("bind() failed with error %d\n", WSAGetLastError());
		goto SOCKET_CLEAN;
	}

	if (listen(listenSock, 5))
	{
		printf("listen() failed with error %d\n", WSAGetLastError());
		goto SOCKET_CLEAN;
	}

	// Change the socket mode on the listening socket from blocking to
	// non-block so the application will not block waiting for requests.

	ULONG NonBlock = 1;
	if (ioctlsocket(listenSock, FIONBIO, &NonBlock) == SOCKET_ERROR)
	{
		printf("ioctlsocket() failed with error %d\n", WSAGetLastError());
		goto SOCKET_CLEAN;
	}

	while(1)
	{
		FD_ZERO(&ReadSet);	
		FD_SET(listenSock, &ReadSet);

		for (i = 0; i < totalSockets; i++)
		{
			FD_SET(SocketArray[i]->Socket, &ReadSet);
		}

		total = select(0,&ReadSet,NULL,NULL,NULL);
		if(total == SOCKET_ERROR)
		{
			printf("select() failed with error %d\n", WSAGetLastError());
			goto SOCKET_CLEAN;
		}

		if(FD_ISSET(listenSock,&ReadSet))
		{
			total--;
			acceptSock = accept(listenSock,NULL,NULL);
			if(acceptSock == INVALID_SOCKET)
			{
				if (WSAGetLastError() != WSAEWOULDBLOCK)
				{
					printf("accept() failed with error %d\n", WSAGetLastError());
					goto SOCKET_CLEAN;
				}
			}else
			{
				NonBlock = 1;
				int ret = ioctlsocket(acceptSock,FIONBIO, &NonBlock);
				if(ret == SOCKET_ERROR)
				{
					printf("ioctlsocket() failed with error %d\n", WSAGetLastError());
					goto SOCKET_CLEAN;
				}

				if (CreateSocketInformation(acceptSock) == FALSE)
					goto SOCKET_CLEAN;
			}
		}


		for (i = 0; total > 0 && i < totalSockets; i++)
		{
			LPSOCKET_INFORMATION SocketInfo = SocketArray[i];

			SocketInfo->DataBuf.buf = SocketInfo->Buffer;
			SocketInfo->DataBuf.len = DATA_BUF_SZIE;

			if(FD_ISSET(SocketInfo->Socket,&ReadSet))
			{
				total--;
				Flags = 0;
				ZeroMemory(SocketInfo->Buffer,DATA_BUF_SZIE);
				if (WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &RecvBytes,
					&Flags, NULL, NULL) == SOCKET_ERROR)
				{
					if (WSAGetLastError() != WSAEWOULDBLOCK)
					{
						printf("WSARecv() failed with error %d\n", WSAGetLastError());
						FreeSocketInformation(i);
					}
					continue;
				}else
				{
					printf(SocketInfo->Buffer);
					if(RecvBytes == 0)
					{
						FreeSocketInformation(i);
						continue;
					}
				}
			}
		}
	}


SOCKET_CLEAN:
	if(listenSock != INVALID_SOCKET)
	{
		closesocket(listenSock);
		listenSock = INVALID_SOCKET;
	}
	if(acceptSock != INVALID_SOCKET)
	{
		closesocket(acceptSock);
		acceptSock = INVALID_SOCKET;
	}
	WSACleanup();

	return 0;
}

 

 

// CommonClient.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <winsock2.h>
#include <conio.h>

#pragma comment(lib,"ws2_32")

#define SOCKET_MAXCNT	64
#define THREAD_NUM		22 
#define CONNECT_PORT	8773	
#define CONNECT_ADDR	"127.0.0.1"

DWORD WINAPI SocketFunc(LPVOID pM) 
{
	char buf[512] = {0};  
	SOCKET	sock;
	int result;
	struct sockaddr_in cli_addr;
	int num = *(int*)pM;

	sock = socket(AF_INET,SOCK_STREAM,0);

	cli_addr.sin_family = AF_INET;
	cli_addr.sin_port = htons(CONNECT_PORT);
	cli_addr.sin_addr.s_addr = inet_addr(CONNECT_ADDR);


	result = connect(sock,(struct sockaddr*)&cli_addr,sizeof(cli_addr));
	if(result == SOCKET_ERROR)
	{
		printf("%d thread: connect error\n",num);
		exit(1);
	}

	while(1)
	{

		sprintf(buf,"%d thread: %s",num,"hello world!\n");
		printf(buf);
		result = send(sock,buf,100,0);
		if(result == SOCKET_ERROR)
		{
			printf("%d error \n",num);
			return 0;
		}
		Sleep(3000);
	}

	exit(1);
	return 0;
}


int _tmain(int argc, _TCHAR* argv[])
{
	int num[SOCKET_MAXCNT] = {0};
	WSADATA	wsa_data;

	WSAStartup(WINSOCK_VERSION,&wsa_data);

	// 初始化数组 传递给线程  区别各个线程号
	for(int i = 0 ;i < SOCKET_MAXCNT;i++)
	{
		num[i] = i;
	}

	for(int i = 0; i < THREAD_NUM;i++)
	{
		HANDLE hThread = CreateThread(NULL,0,SocketFunc,&num[i],0,NULL);
		if(hThread != NULL)
		{
			CloseHandle(hThread);
		}
	}

	while(1)
	{
		Sleep(100000);
	}


	return 0;
}

 

posted on 2014-06-01 13:32  itdef  阅读(545)  评论(0)    收藏  举报

导航