阻塞I/O模型的测试

  1. 客户端的代码:(这份test_client的代码也会为后续的I/O模型做测试)
#include<WinSock2.h>
#include<WS2tcpip.h>
#include<stdlib.h>
#include<stdio.h>
#include<iostream>
using namespace std;

#pragma comment(lib,"ws2_32.lib")
#define DEF_PORT	27015
#define DEF_SIZE	512

int main()
{
	WSADATA wsaData;
	SOCKET ConnectSocket = INVALID_SOCKET;
	int iResult;
	//初始化Winsock
	iResult = WSAStartup(MAKEWORD(2,2),&wsaData);
	if(iResult != 0){
		cout<<"WSAStartup failed with error: "<<iResult<<endl;
        return 1;
	}

	//创建用于连接的socket
	
	ConnectSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_IP);

	if(ConnectSocket == INVALID_SOCKET){
		cout<<"socket created with error: "<<GetLastError()<<endl;
		WSACleanup();
		return 1;
	}
	
	//连接
	sockaddr_in addserver;
	addserver.sin_family = AF_INET;
	addserver.sin_port = htons(DEF_PORT);
	addserver.sin_addr.S_un.S_addr = inet_addr("10.50.92.211");

	//连接
	iResult  = connect(ConnectSocket,(const sockaddr*)&addserver,sizeof(addserver));
	if(iResult != 0){
		printf("connect failed with error :%d\n",GetLastError());
		closesocket(ConnectSocket);
		WSACleanup();
		return 1;
	}
	char sendbuf[DEF_SIZE];
	printf("conntect successful...\n");
	printf("Please input sendbuf:");
	cin>>sendbuf;
	//发送数据
	iResult = send(ConnectSocket,sendbuf,sizeof(sendbuf),0);
	if(iResult > 0){
		printf("host send: %s\n",sendbuf);
	}
	closesocket(ConnectSocket);
	WSACleanup();
	system("pause");
	return 0;
}
  1. 使用阻塞I/O的服务器代码:
#include<WinSock2.h>
#include<WS2tcpip.h>
#include<stdlib.h>
#include<stdio.h>
#include<iostream>
using namespace std;

#pragma comment (lib,"ws2_32.lib")

#define DEF_PORT	27015
#define DEF_SIZE	512


int main()
{
	WSADATA wsaData;
	int iResult;
	SOCKET ListenSocket = INVALID_SOCKET;
	SOCKET AcceptSocket = INVALID_SOCKET;
	

	//1.初始化
	iResult = WSAStartup(MAKEWORD(2,2),&wsaData);
	if(iResult != 0)
	{
		printf("WSAStartup failed with error :%d\n",iResult);
		return 1;
	}

	//2.创建用于监听的套接字
	ListenSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
	if(ListenSocket == INVALID_SOCKET){
		printf("create ListenSocket failed with error:%d\n",GetLastError());
		WSACleanup();
		return 1;
	}
	//3.为监听套接字绑定地址和端口号
	sockaddr_in addServer;

	addServer.sin_family = AF_INET;
	addServer.sin_port = htons(DEF_PORT);
	addServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

	iResult = bind(ListenSocket,(const sockaddr*)&addServer,sizeof(addServer));
	if(iResult == SOCKET_ERROR){
		printf("bind failed with error:%d",GetLastError());
		closesocket(ListenSocket);
		WSACleanup();
		return 1;
	}

	/*监听客户端的连接
		如果设置为SOMAXCONN,则负责套接字的底层服务提供程序会将backlog设置为最大合理值。*/
	iResult = listen(ListenSocket,SOMAXCONN);
	if(iResult == SOCKET_ERROR){
		printf("Listen failed with error:%d\n",GetLastError());
		closesocket(ListenSocket);
		WSACleanup();
		return 1;
	}
	printf("TCP Server is starting...\n");

	sockaddr_in addClient;
	int addClient_Size = sizeof(addClient);
	char recvbuf[DEF_SIZE] = {0};
	int  recvlen = sizeof(recvbuf);
	//循环等待客户请求建立连接,并处理连接请求
	while(1){
		AcceptSocket = accept(ListenSocket,(sockaddr*)&addClient,&addClient_Size);
		
		if(AcceptSocket == INVALID_SOCKET){
			printf("accpet failed!\n");
			closesocket(ListenSocket);
			WSACleanup();
			return 1;
		}
		printf("收到新的连接:%s\n",inet_ntoa(addClient.sin_addr));
		//循环接收数据
		while(1){
			memset(recvbuf,0,sizeof(recvbuf));
			iResult = recv(AcceptSocket,recvbuf,recvlen,0);
			if(iResult > 0){
				printf("数据内容: %s\n",recvbuf);
				continue;
			}
			else if(iResult == 0){		//返回值0代表正常关闭	
				printf("客户端已经正常关闭....\n");
				closesocket(AcceptSocket);
				break;
			}
			else{	//接收出现错误
				printf("recv failed with error: %d\n",GetLastError());
				closesocket(AcceptSocket);
				closesocket(ListenSocket);
				WSACleanup();
				return 1;
			}
		}
	}
	closesocket(AcceptSocket);
	closesocket(ListenSocket);
	WSACleanup();
	system("pause");
	return 0;
}
  1. 测试结果:
    在这里插入图片描述
  2. 模型评价:
    阻塞I/O模型是网络通信中最常用的一种,优点是简单直接,缺点就是在处理多个套接字连接的时候,串行处理多套接字的I/O操作会导致处理时间延长、程序的执行效率降低。
    这种情况下我们关心的是如何及时处理多个I/O请求,有两种解决方案:
    (1)使用多线程并发处理多个I/O请求,只要来一个I/O请求,就生成一个线程去解决,但是会增加线程的启动和终止,以及维护线程运行时间和同步操作。而且个人觉得线程数量太多也是一种资源的消耗。增大了系统开销和程序的复杂度
    (2)异步、非阻塞的处理多个I/O请求,也就是之后的I/O模型

猜你喜欢

转载自blog.csdn.net/bryant_xw/article/details/88916178
今日推荐