Blocking test of write and read functions in linux

Original: https://blog.csdn.net/hyman_c/article/details/52979317

When you first come into contact with network programming, it is easy to be confused by the interaction between the client and the server. For example, the blocking and non-blocking of various functions is a headache. For example, in my impression, the write() function and read() function used to read and write file descriptors in Linux are non-blocking functions, but in a network communication experiment, they were found to be blocking. Later, man After reading write and read, I found the following sentence in the document:

ERRORS 
       EAGAIN The file descriptor fd refers to a file other than a  socket  and  has  been
              marked non-blocking (O_NONBLOCK), and the write would block.

The translation is:
if the file descriptor is not a socket, the function is non-blocking, otherwise the function is blocking. In order to verify this problem, the following experiments are carried out to verify the blocking characteristics of the read function (to verify that the write function needs to fill the output buffer, I will not!!!)

First write the socket server-side program:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<arpa/inet.h>
 
#define BUF_SIZE 100 
 
void error_handling(char* message);
 
int main(int argc,char* argv[])
 
{
	int serv_sock,clnt_sock;
	struct sockaddr_in serv_addr,clnt_addr;
	int clnt_addr_sz;
	int str_len,i,j;
	char buf[BUF_SIZE];
 
	if(argc!=2)
	{
		printf("Usage %s <port>\n",argv[0]);
		exit(1);
	}
	//创建socket
	serv_sock=socket(AF_INET,SOCK_STREAM,0);
	if(serv_sock==-1)
		error_handling("socket error");
	//填充地址信息
	memset(&serv_addr,0,sizeof(serv_addr));
	serv_addr.sin_family=AF_INET;
	serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
	serv_addr.sin_port=htons(atoi(argv[1]));
	//socket和ip地址的绑定
	if(bind(serv_sock,(struct sockaddr*)&serv_addr,sizeof(serv_addr))==-1)
		error_handling("bind error");
	//开启监听
	if(listen(serv_sock,5)==-1)
		error_handling(" listen error");
    	sleep(10);
	for(i=0;i<5;i++)
	{
		clnt_addr_sz=sizeof(clnt_addr);
		clnt_sock=accept(serv_sock,(struct sockaddr*)&clnt_addr,&clnt_addr_sz);
		if(clnt_sock==-1)
			error_handling("accept error");
		else
			printf("clnt:%s connected\n",inet_ntoa(clnt_addr.sin_addr));
		//接受数据
		while(1)
		{
			str_len=read(clnt_sock,buf,BUF_SIZE);
				write(clnt_sock,buf,str_len);
			memset(buf,0,sizeof(buf));
			if(str_len<=0)
				break;
		}
		close(clnt_sock);
	}
	close(serv_sock);
	return 0;
}
 
 
void error_handling(char* message)
{
	fputs(message,stderr);
	fputc('\n',stderr);
	exit(1);
}

Please pay attention to sleep(10) after calling listen() to turn on the monitoring. We let the server sleep for 10s to verify that the client program is blocked when reading, and the blocking state ends after the server wakes up

Client code:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<time.h>
#define BUF_SIZE 10000000
 
void print_time();
 
void error_handling(const char* message);
 
int main(int argc,char* argv[])
{
	int sock;
	struct sockaddr_in serv_addr;
	int str_len;
	char buf[BUF_SIZE];
	int recv_len=0;
	//创建socket
	sock=socket(AF_INET,SOCK_STREAM,0);
	if(sock==-1)
		error_handling("socket error");
 
	//准备地址
	memset(&serv_addr,0,sizeof(serv_addr));
	serv_addr.sin_family=AF_INET;
	serv_addr.sin_addr.s_addr=inet_addr(argv[1]);
	serv_addr.sin_port=htons(atoi(argv[2]));
 
	//链接
	if(connect(sock,(struct sockaddr*)&serv_addr,sizeof(serv_addr))==-1)
		error_handling("connect error");
	else
	        puts("connect succeed");
	while(1)
	{
		memset(buf,0,BUF_SIZE);
		fputs("请输入数据:",stdout);
		fgets(buf,BUF_SIZE,stdin);
		if(!strcmp(buf,"q\n")||!strcmp(buf,"Q/n"))
			break;
 
		str_len=write(sock,buf,strlen(buf));
		puts("writed,begin block");
		print_time();
		sizeof(buf,0,sizeof(buf));
		while(recv_len<str_len)
			recv_len+=read(sock,buf,BUF_SIZE-1);
		puts("end block");
		print_time();
		buf[str_len]=0;
		printf("服务器传回信息:%s\n",buf);
	}
	close(sock);
	return 0;
}
 
void print_time()
{
  time_t now=time(0);
	struct tm* ptm=localtime(&now);
	char buf[256]={0};
	sprintf(buf,"time now:[%02d-%02d-%02d %02d:%02d:%02d]",
  		ptm->tm_year+1900,
			ptm->tm_mon+1,
			ptm->tm_mday,
			ptm->tm_hour,
			ptm->tm_min,
			ptm->tm_sec);
	puts(buf);
}
 
void error_handling(const char* message)
{
	fputs(message,stderr);
	fputc('\n',stderr);
	exit(1);
}

Client after write, print out the information "writed, begin block" and then read start blocking function, finished only sleep in the service side, blocking will end after the data is returned the following results:
server -

[Hyman@Hyman-PC echoSever]$ ./serv 9190
time now:[2016-10-09 09:28:04]
clnt:127.0.0.1 connected

Client-

[Hyman@Hyman-PC echoSever]$ ./clnt 127.0.0.1 9190
connect succeed
请输入数据:helo
writed,begin block
time now:[2016-10-09 09:28:01]
end block
time now:[2016-10-09 09:28:04]
服务器传回信息:helo

The above code is sufficient to prove the blocking characteristics of the read function. . . . .

Github location:
https://github.com/HymanLiuTS/NetDevelopment
Clone this project:
git clone [email protected]:HymanLiuTS/NetDevelopment.git
Get the source code of this article:
git checkout NL24

Guess you like

Origin blog.csdn.net/xiaolei251990/article/details/83586973