Linux read() 在套接字编程中不会阻塞
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12773509/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
read() is not blocking in socket programming
提问by Mathew
I have a server that sends data to a client every 5 seconds. I want the client to block on read() until the server sends some data and then print it. I know read () is blocking by default. My problem is that my client is not blocking on read(). This is very odd and this does not seem to be a normal issue.
我有一个服务器,每 5 秒向客户端发送一次数据。我希望客户端在 read() 上阻塞,直到服务器发送一些数据然后打印它。我知道 read () 默认情况下是阻塞的。我的问题是我的客户端没有阻塞 read()。这很奇怪,这似乎不是正常问题。
My code prints "Nothing came back" in an infinite loop. I am on a linux machine, programming in c. My code snippet is below. Please advice.
我的代码在无限循环中打印“什么都没有回来”。我在一台 linux 机器上,用 c 编程。我的代码片段如下。请指教。
while(1)
{
n = read(sockfd, recvline, MAXLINE);
if ( n > 0)
{
recvline[n] = 0;
if (fputs(recvline, stdout) == EOF)
printf("fputs error");
}
else if(n == 0)
printf("Nothing came back");
else if (n < 0)
printf("read error");
}
return;
采纳答案by Grijesh Chauhan
There may be several cause and several exceptions are possible at different place:
可能有多种原因,不同地方可能出现多种异常:
check socket where you create:
sockfd=socket(AF_INET,SOCK_STREAM,0); if (sockfd==-1) { perror("Create socket"); }
You and also enable blocking mode explicitly before use it:
// Set the socket I/O mode: In this case FIONBIO // enables or disables the blocking mode for the // socket based on the numerical value of iMode. // If iMode = 0, blocking is enabled; // If iMode != 0, non-blocking mode is enabled. ioctl(sockfd, FIONBIO, &iMode);
or you can use
setsockopt
as below:struct timeval t; t.tv_sec = 0; tv_usec = 0; setsockopt( sockfd, // Socket descriptor SOL_SOCKET, // To manipulate options at the sockets API level SO_RCVTIMEO,// Specify the receiving or sending timeouts const void *(&t), // option values sizeof(t) );
Check Read function call (Reason of bug)
n = read(sockfd, recvline, MAXLINE); if(n < 0){ perror("Read Error:"); }
Also check server code!:
May your server send some blank(non-printable, null, enter) charter(s). And your are unaware of this. Bug you server code too.
Or your server terminated before your client can read.
One more interesting thing, Try to understand:
When you call N
write()
at server its not necessary there should be Nread()
call at other side.
检查您创建的套接字:
sockfd=socket(AF_INET,SOCK_STREAM,0); if (sockfd==-1) { perror("Create socket"); }
您还可以在使用前显式启用阻塞模式:
// Set the socket I/O mode: In this case FIONBIO // enables or disables the blocking mode for the // socket based on the numerical value of iMode. // If iMode = 0, blocking is enabled; // If iMode != 0, non-blocking mode is enabled. ioctl(sockfd, FIONBIO, &iMode);
或者你可以使用
setsockopt
如下:struct timeval t; t.tv_sec = 0; tv_usec = 0; setsockopt( sockfd, // Socket descriptor SOL_SOCKET, // To manipulate options at the sockets API level SO_RCVTIMEO,// Specify the receiving or sending timeouts const void *(&t), // option values sizeof(t) );
检查读取函数调用(错误原因)
n = read(sockfd, recvline, MAXLINE); if(n < 0){ perror("Read Error:"); }
还要检查服务器代码!:
愿您的服务器发送一些空白(不可打印,空,输入)章程。而你对此一无所知。也让你的服务器代码出错。
或者您的服务器在您的客户端可以读取之前终止。
一件更有趣的事情,试着理解:
当您
write()
在服务器上调用 N 时,不需要read()
在另一端调用N。
回答by Hong Zhou
What is the value of MAXLINE?
MAXLINE 的价值是什么?
If the value is 0, then it will return 0 as well. Otherwise, as Grijesh Chauhan mention, set it explcitly to blocking.
如果值为 0,则它也将返回 0。否则,正如 Grijesh Chauhan 提到的,将其明确设置为阻塞。
Or, you may also consider using recv() where blocking and non-blocking can be specified. It has the option, MSG_WAITALL, where it will block until all bytes arrived.
或者,您也可以考虑使用 recv() 来指定阻塞和非阻塞。它有选项 MSG_WAITALL,它将阻塞直到所有字节到达。
n = recv(sockfd, recvline, MAXLINE, MSG_WAITALL);
回答by glglgl
What Greg Hewgill already wrote as a comment: An EOF (that is, an explicit stop of writing, be it via close()
or via shutdown()
) will be communicated to the receiving side by having recv()
return 0. So if you get 0, you know that there won't be any data and you can terminate the reading loop.
Greg Hewgill 已经写的评论:EOF(即明确停止写入,无论是通过close()
还是通过shutdown()
)将通过recv()
返回 0传达给接收方。所以如果你得到 0,你就知道赢了'不是任何数据,您可以终止读取循环。
If you had non-blocking enabled and there are no data, you will get -1
and errno
will be set to EAGAIN
or EWOULDBLOCK
.
如果你有非阻断启用,并且没有数据,你会得到-1
和errno
将被设置为EAGAIN
或EWOULDBLOCK
。