赞
踩
marked non-blocking (O_NONBLOCK), and the write would block.
翻译过来就是:
如果文件描述符不是socket的话,该函数是非阻塞的,否则该函数是阻塞的。 为了验证这个问题,进行如下实验,主要验证read函数的阻塞特性(验证write函数需要填充满输出缓冲区,我不会!!!)
首先编写socket服务器端程序:
- #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);
- }
请留意在调用 listen()开启监听后的sleep(10),我们让服务器睡了10s中,以此来验证客户端程序在read时发生阻塞,服务器 睡醒后才结束阻塞状态。
- #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);
- }
[Hyman@Hyman-PC echoSever]$ ./serv 9190
time now:[2016-10-09 09:28:04]
clnt:127.0.0.1 connected
[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
以上代码,足以证明了read函数的阻塞特性。。。。。
Github位置:
https://github.com/HymanLiuTS/NetDevelopment
克隆本项目:
git clone git@github.com:HymanLiuTS/NetDevelopment.git
获取本文源代码:
git checkout NL24
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。