select连接TCPIP数据收发测试

本文介绍了使用非阻塞模式的TCP客户端和服务端进行高效数据传输的方法,包括如何通过select模型实现并发处理多个连接,以及在服务端接收100MB数据并响应客户端的方法。同时,提供了TCP发送端的实现,展示了如何通过循环发送大量数据并接收确认信息。


下面给出一个简单的select模型的服务端套接字,非阻塞模式。连接1个客户端,接收100MB数据后,返回OK退出。

//服务端,接收端
int SelectTcpRecver1()
{
	SOCKET        sListen, sClient;
	int           iAddrSize;
	//HANDLE        hThread;DWORD         dwThreadId;
	struct sockaddr_in local, client;
	iAddrSize = sizeof(client);

	sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
	if (sListen == SOCKET_ERROR)
	{
		printf("socket() failed: %d\n", WSAGetLastError());
		return 1;
	}

	local.sin_addr.s_addr = htonl(INADDR_ANY);
	local.sin_family = AF_INET;
	local.sin_port = htons(TCPSERVER_PORT);

	if (bind(sListen, (struct sockaddr *)&local,
		sizeof(local)) == SOCKET_ERROR)
	{
		printf("bind() failed: %d\n", WSAGetLastError());
		return -11;
	}
	if (listen(sListen, 8))
	{
		printf("listen Error:%d\n", WSAGetLastError());
		return -2;
	}
	
	//ULONG NonBlock = 1;
	//if (ioctlsocket(sListen, FIONBIO, &NonBlock) == SOCKET_ERROR){
	//	printf("ioctlsocket() failed with error %d\n", WSAGetLastError());
	//	return -3;
	//}

	printf("进入监听状态\n");
	    
	int loopi = 0;
	timeval tv;     
	FD_SET SelectSet;
	
	while (1)
	{

		FD_ZERO(&SelectSet);//初始化fd_set
		FD_SET(sListen, &SelectSet);//分配套接字句柄到相应的fd_set
		tv.tv_sec = 2;//这里我们打算让select等待两秒后返回,避免被锁死,也避免马上返回
		tv.tv_usec = 0;
		select(0, &SelectSet, NULL, NULL, &tv);

		loopi++;

		if (FD_ISSET(sListen, &SelectSet))//如果套接字句柄还在fd_set里,说明客户端已经有connect的请求发过来了,马上可以accept成功
		{
			sClient = accept(sListen, (struct sockaddr *)&client, &iAddrSize);
			if (sClient == INVALID_SOCKET){
				printf("accept() failed: %d\n", WSAGetLastError());
				break;
			}
			else
			{
				printf("Accepted client: %s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
				break;
				
			}
		}
		else//还没有客户端的connect请求,我们可以去做别的事,避免像没有用select方式的阻塞套接字程序被锁死的情况,如果没用select,当程序运行到accept的时候客户端恰好没有connect请求,那么程序就会被锁死,做不了任何事情
		{
			printf("wait ......%d\r",loopi);
			//::MessageBox(NULL, "waiting...", "recv", MB_ICONINFORMATION);//别的事做完后,继续去检查是否有客户端连接请求
		}
	
	}

	char * Buffer = (char *)malloc(MB100);
	if (NULL == Buffer)
	{
		printf("100MB 内存分配失败!\n");
		return -1;
	}
	DWORD nRemainRecv = MB100;
	char * pBuf = (char *)Buffer;
	int len,ret;
	//接收100MB的数据
	while (nRemainRecv > 0)
	{
		len = recv(sClient, pBuf, nRemainRecv, 0);
		if (len < 0){
			printf("Recv HeadDate Fail:%d\n", len);
			break;
		}
		else if (len == 0){
			printf("Pre len is 0 client quit!\n");
			break;
		}
		printf("接收数据:%d\n", len);
		nRemainRecv -= len;
		pBuf += len;
	}
	free(Buffer);
	printf("共接收数据:%d\n", MB100);
	char   szBuff[8];
	sprintf_s(szBuff, _countof(szBuff), "%s", "OK");
	ret = send(sClient, szBuff, (int)strlen(szBuff), 0);
	if (ret == 0)printf("send 0\n");
	else if (ret == SOCKET_ERROR)
	{
		printf("send() failed: %d\n", WSAGetLastError());
	}
	closesocket(sClient);


	closesocket(sListen);

	return 0;
}


发送端:

int TcpSender()
{
	
	SOCKET        sClient;
	
	int           ret;
	struct sockaddr_in server;
	struct hostent    *host = NULL;

	
	sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (sClient == INVALID_SOCKET)
	{
		printf("socket() failed: %d\n", WSAGetLastError());
		return 1;
	}
	ZeroMemory(&server, sizeof(sockaddr_in));
	server.sin_family = AF_INET;
	server.sin_port = htons(TCPSERVER_PORT);
	server.sin_addr.s_addr = inet_addr(ServerIp);
	if (server.sin_addr.s_addr == INADDR_NONE)
	{
		host = gethostbyname(ServerIp);
		if (host == NULL)
		{
			printf("Unable to resolve server: %s\n", ServerIp);
			return 1;
		}
		CopyMemory(&server.sin_addr, host->h_addr_list[0],host->h_length);
	}
	printf("We are trying to connect to %s:%d...\n", inet_ntoa(server.sin_addr), htons(server.sin_port));
	if (connect(sClient, (struct sockaddr *)&server,sizeof(server)) == SOCKET_ERROR)
	{
		printf("connect() failed: %d\n", WSAGetLastError());
		return 1;
	}
	//准备发送100MB的数据

	char * Buffer = (char *)malloc(MB100);
	if (NULL == Buffer)
	{
		printf("100MB 内存分配失败!\n");
		return -1;
	}
	memset(Buffer, '#', MB100);
	int nLeft = MB100;
	int idx = 0;
	
	DWORD lt1, lt2,lt;
	int i = 0;

	lt1 = timeGetTime();
	//int len1 = 65535;

	while (nLeft > 0)
	{
		lt2 = timeGetTime();
	/*	if (nLeft > len1)len1 = 65536;
		else len1 = nLeft;*/
		//Sleep(5);
		ret = send(sClient, &Buffer[idx], nLeft, 0);
		if (ret == 0){
			printf("send is 0,%d\n", WSAGetLastError());
			break;
		}
		else if (ret == SOCKET_ERROR)
		{
			printf("send() failed: %d\n", WSAGetLastError());
			break;
		}
		lt = timeGetTime() - lt2;
		//if(lt > 50)
			printf("i:%d,Send %d bytes,耗时:%d\n",i, ret,lt);
		i++;
		nLeft -= ret;
		idx += ret;
	}
	printf("100MB 发送完成:%d\n", timeGetTime() - lt1);
	//接收确认的信息
	char  szBuf[8];
	ret = recv(sClient, szBuf, sizeof(szBuf), 0);
	if (ret == 0){
		printf(" Graceful close\n");
	}
	else if (ret == SOCKET_ERROR)
	{
		printf("recv() failed: %d,共计消耗时间%d\n", WSAGetLastError(),timeGetTime() - lt2);

	}
	else
	{
		szBuf[ret] = '\0';
		printf("RECV [%d bytes]: '%s'\n", ret, szBuf);
		printf("接收确认信息:%d\n", timeGetTime() - lt2);
	}
	free(Buffer);
	closesocket(sClient);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值