服务端用非阻塞socket<--->客户端用阻塞socket

972 篇文章 329 订阅
147 篇文章 46 订阅

       之前, 我们简要第了解了一下非阻塞的socket。 在本文中, 我们让服务端用非阻塞socket, 客户端依然用我们熟悉的阻塞的socket.

 

       服务端程序如下(非阻塞的socket):

 

#include <stdio.h>
#include <winsock2.h>   
#include <windows.h>
#pragma comment(lib, "ws2_32.lib")   

int main()
{
	// 网络初始化
	WSADATA wsd;   
    WSAStartup(MAKEWORD(2,2), &wsd);


	// 默认为阻塞socket
    SOCKET sServer = socket(AF_INET,SOCK_STREAM, 0);    
   

	// 设置为非阻塞socket
	int iMode = 1;
	ioctlsocket(sServer, FIONBIO, (u_long FAR*)&iMode);


    // 设置服务器套接字地址   
    SOCKADDR_IN addrServ;   
    addrServ.sin_family = AF_INET;   
    addrServ.sin_port = htons(8888);
    addrServ.sin_addr.S_un.S_addr = htonl(INADDR_ANY);    
    bind(sServer,(const struct sockaddr*)&addrServ,sizeof(SOCKADDR_IN));   
   

	// 用耳朵听听
    listen(sServer, 5);   
    

    // 接受客户请求 
	printf("accept\n");
    sockaddr_in addrClient;
    int len = sizeof(addrClient);   
	SOCKET sClient = 0; 
	while(1)
	{
		sClient = accept(sServer,(sockaddr FAR*)&addrClient, &len);   
		if(INVALID_SOCKET == sClient)   
		{   
			int err = WSAGetLastError();
			if(WSAEWOULDBLOCK == err)  // 没有客户端来connect
			{
				Sleep(100);
				continue;
			}

			// 其实这里还应该考虑一下异常比较好
		} 

		printf("accept ok\n");
		break;
	}

	int iRet = -1;
	while(1)
	{
		char szRecvBuf[100] = {0};
		iRet = recv(sClient, szRecvBuf, sizeof(szRecvBuf), 0);
		if(SOCKET_ERROR == iRet)   
		{   
			int err = WSAGetLastError();
			if(WSAEWOULDBLOCK == err) // 接收socket对应的内核缓冲区中暂时没有数据
			{
				Sleep(100);
				continue;
			}

			// 这里考虑一下异常比较好
		}  
		
		printf("%s\n", szRecvBuf);
		break;
	}


	// 网络释放
	closesocket(sServer);   
    closesocket(sClient);   
    WSACleanup();  
	return 0;
}

      运行程序, 开启服务端进程。

 

 

      下面, 我们看看客户端的程序(阻塞的socket):

#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")

int main()
{
	WORD wVersionRequested;
	WSADATA wsaData;
	wVersionRequested = MAKEWORD(2, 2);
	
	WSAStartup( wVersionRequested, &wsaData );

	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_family = AF_INET;
	addrSrv.sin_port = htons(8888);
	connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));

	send(sockClient, "hello world", strlen("hello world") + 1, 0);

	closesocket(sockClient);
	WSACleanup();

	return 0;
}

      运行该程序。

 

 

      服务端进程打印的结果为:

accept
accept ok
hello world

 

      最后, 根据实践的结果, 我不得不在这里强调一下: 服务端的recv函数是否阻塞, 并不取决于客户端的sockClient是否是阻塞式的, 而是取决于服务端的sServer是否为阻塞式的, 所以, 上面服务端的recv并不会阻塞。

 

      好, 本文我们就先学到这里。

 


 

 

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值