VC6.0下select+多线程基于TCP的网络通信

花了差不多四五天写的控制台应用程序,还是仿照别人写的,当然也结合了很多版本的精华,再加入自己的一些理解。本人菜鸟,刚学WinSocket编程,贴出代码,记录一下自己的成果~

//客户端
#pragma comment(lib, "Ws2_32.lib")
#include <Winsock2.h>
#include <stdio.h>
void main()
{
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	
	wVersionRequested = MAKEWORD( 1, 1 );
	
	err = WSAStartup( wVersionRequested, &wsaData );
	if ( err != 0 ) {
		return;
	}
	
	if ( LOBYTE( wsaData.wVersion ) != 1 ||
		HIBYTE( wsaData.wVersion ) != 1 ) {
		/* Tell the user that we could not find a usable */
		/* WinSock DLL.                                  */
		WSACleanup( );
		return;
	}
	SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);
	SOCKADDR_IN addrSrv;//服务端信息
	addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
	addrSrv.sin_port=htons(6000);
	addrSrv.sin_family=AF_INET;
	int h=connect(sockClient,(sockaddr*)&addrSrv,sizeof(sockaddr));
	if(h==0) printf("connect is successful\n");
	while(1)
	{
		char sendBuffer[100]={"I am a Client."};
		char recvBuffer[100]={0};
		int j=recv(sockClient,recvBuffer,50,0);
		printf("%s",recvBuffer);
		int p=send(sockClient,sendBuffer,20,0);
		Sleep(5000);
	}
	closesocket(sockClient);
	WSACleanup();
}

//本工程还需链接一个库文件
//解决方案一:程序代码中加入#pragma comment(lib, "Ws2_32.lib")
//解决方案二:在project\setting\link 中object/library modules加入 ws2_32.lib
//服务端
#pragma comment(lib, "Ws2_32.lib")
#include <Winsock2.h>
#include <stdio.h>
SOCKADDR_IN addrClient;
int len=sizeof(sockaddr);
DWORD WINAPI WorkerThread(LPVOID lpParameter);
DWORD WINAPI WriteThread(LPVOID lpParameter);
HANDLE hMutex;
fd_set sfread,sfwrite;
int iTotalClient=0;
struct timeval tv={1,0};
SOCKET ClientArr[FD_SETSIZE];
void main()
{
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	
	wVersionRequested = MAKEWORD( 1, 1 );
	
	err = WSAStartup( wVersionRequested, &wsaData );
	if ( err != 0 ) {                              
		return;
	}                                      
	
	if ( LOBYTE( wsaData.wVersion ) != 1 ||
		HIBYTE( wsaData.wVersion ) != 1 ) {
		/* Tell the user that we could not find a usable */
		/* WinSock DLL.                                  */
		WSACleanup( );
		return; 
	}
	SOCKET sockRrv=socket(AF_INET,SOCK_STREAM,0);
    SOCKADDR_IN addrSrv;
	addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
	addrSrv.sin_port=htons(6000);
	addrSrv.sin_family=AF_INET;
	bind(sockRrv,(SOCKADDR *)&addrSrv,sizeof(sockaddr));
	printf("绑定成功!\n");
	listen(sockRrv,5);
	printf("监听成功!\n");

    CreateThread(NULL,0,WorkerThread,NULL,0,0);
	CreateThread(NULL,0,WriteThread,NULL,0,0);
	hMutex=CreateMutex(NULL,FALSE,NULL);

	while(1)
	{
		
		SOCKET sockConn=accept(sockRrv,(SOCKADDR *)&addrClient,&len);
		printf("Accepted:Client %s:%d \n",inet_ntoa(addrClient.sin_addr),ntohs(addrClient.sin_port));
		ClientArr[iTotalClient++]=sockConn;

		//closesocket(sockConn);
	}
}
DWORD WINAPI WorkerThread(LPVOID lpParameter)
{
	
	char recvBuffer[100]={0};
	//	printf("%s\n",recvBuffer);
	while(1)
	{
		WaitForSingleObject(hMutex,INFINITE);
		FD_ZERO(&sfread);
		for(int k=0;k<iTotalClient;k++)
		{
			FD_SET(ClientArr[k],&sfread);
		}
		
		int iRet=select(0,&sfread,NULL,NULL,&tv);
		if(iRet==SOCKET_ERROR)
		{
			printf("此时没有客户连接\n");
			ReleaseMutex(hMutex);
			Sleep(5000);
			continue;
		}
	
		if(iRet==0)
		{
			printf("此时没有数据可读!\n");
			ReleaseMutex(hMutex);
			Sleep(5000);
			continue;
		
		}
		printf("此时总共有%d个客户连接,有%d个客户可读!\n",iTotalClient,iRet);
		for(int i=0;i<iTotalClient;i++)
		{
			if(FD_ISSET(ClientArr[i],&sfread)) 
			{
				int j=recv(ClientArr[i],recvBuffer,100,0);
				if(j==SOCKET_ERROR&&WSAGetLastError()==WSAECONNRESET)
				{
					printf("Client socket %d断开连接\n",ClientArr[i]);
					if(j==iTotalClient-1)
					{
						Sleep(5000);
						--iTotalClient;
					}
					else
					{
						Sleep(5000);
						ClientArr[i]=ClientArr[iTotalClient-1];
						--i;
						iTotalClient--;
					}
				}
				else 
					if(j==0)
					{		
						printf("Client socket %d超时\n",ClientArr[i]);
						if(i==iTotalClient-1)
						{
							--iTotalClient;
						}
						else
						{
							ClientArr[i]=ClientArr[iTotalClient-1];
							--i;
							iTotalClient--;
						}
					}
					else
					{
						printf("%s %d\n",recvBuffer,strlen(recvBuffer));
					}
				          
			}
		
		}
		Sleep(5000);
		ReleaseMutex(hMutex);
		
	}
	//printf("共接收%d个字节\n",i);
	//printf("接收成功!\n");
	
	return 0;
}
DWORD WINAPI WriteThread(LPVOID lpParameter)
{
	/*可写性检查*/
	char sendBuffer[100]="hello world\n";		
	while(1)
	{
		WaitForSingleObject(hMutex,INFINITE);
		FD_ZERO(&sfwrite);
		for(int p=0;p<iTotalClient;p++)
		{
			FD_SET(ClientArr[p],&sfwrite);
		}
		int iWriter=0;
		iWriter=select(0,NULL,&sfwrite,NULL,&tv);
		if(iWriter==SOCKET_ERROR)
		{
			printf("此时没有客户连接\n");
			Sleep(5000);
			ReleaseMutex(hMutex);
			continue;
		}
		
		if(iWriter==0)
		{
			printf("此时没有数据可写!\n");
			ReleaseMutex(hMutex);
			Sleep(5000);
			continue;
			
		}
		printf("此时共有%d个客户连接,有%d个客户可读\n",iTotalClient,iWriter);
		for(int t=0;t<iTotalClient;t++)
		{
			if(FD_ISSET(ClientArr[t],&sfwrite)) 
			{
				int nSend=send(ClientArr[t],sendBuffer,strlen(sendBuffer),0);
				if(nSend==SOCKET_ERROR)
					printf("Client Socket %d 发送失败!\n",ClientArr[t]);
				printf("Client Socket %d 发送成功!\n",ClientArr[t]);
			}
		}
		Sleep(5000);
		ReleaseMutex(hMutex);
		
	}
	return 0;
}


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值