2009-11-25 97 views
7

在Linux中的套接字编程中我需要在套接字中写入数据,但我不知道套接字是打开还是关闭。如何知道该套接字是打开并关闭而未读取的?检查连接是否打开或关闭?(在Linux中为C)

printf("befor read%d\n", n); 
bzero(buffer, MAX_SIZE_BUFFER); 
n = read(sockfd, buffer, MAX_SIZE_BUFFER - 1); 
printf("after read%d\n", n); 
if (n <= 0) 
{ 
    break; 
} 
printf("befor write%d, s: %d \n", n , sockfd); 

n = write(newsockfd, buffer, n); 
if (n <= 0) 
{ 
    break; 
} 

我从sockfd读取,我确信这个连接是打开的。何时在newsockfd中写缓冲区我不知道newsockfd是打开还是关闭如何检查newsockfd是否已关闭?


我知道问题。在书写连接中间关闭。例如在500个连接关闭并写入程序时写入1024个数据。如何避免这一点?

回答

11

我使用发送()代替写(),该处理没有信号:

bzero(buffer, MAX_SIZE_BUFFER); 
n = read(sockfd, buffer, MAX_SIZE_BUFFER - 1); 
printf("after read%d\n", n); 
if (n <= 0) 
{ 
    break; 
} 
n2 = send(newsockfd, buffer, n, MSG_NOSIGNAL); 
if (n2 == -1) 
{ 
    close(sockfd); 
    close(newsockfd); 
    return; 
} 
if (n2 != n) 
{ 
    break; 
} 
中的下一行
+0

这会起作用,另一种选择是使用'sigaction'来忽略'SIGPIPE'(将其处理程序设置为'SIG_IGN')。 – caf 2009-11-25 12:42:56

15

检查,如果你可以写一个插座,奇怪的是,尝试如果已经关闭了套接字写吧:-)

的样子,你会从write,你会得到一个-1返回码可以检查errno以查看问题所在。

如果套接字仍然有效,但你不能在此刻写入任何数据,write将返回0。read通话也表现在以类似的方式,返回-1如果有一个问题。

基本上,write

  • ,如果你得到一个-1,还有的是一个问题,你应该检查errno,看它是否是可回收或可致命。
  • 如果你找回0,那么你现在不能写任何东西(可能是网络积压或其他问题,但绝对不是(致命的))。
  • 如果您获得的价值低于您的要求,那么部分的数据已发送。调整你的指针,这样你可以尝试在下一个周期中发送剩下的指针。如果不是假定正返回值表示整个块已经发送。
  • 如果您返回的数字与您尝试发送的字节数相同,则整个缓冲区已被接受发送。
  • 如果您回复的内容超过您要求发送的内容,请发送电子邮件给内核开发人员,并提供一些尖锐的评论。莱纳斯等人会喜欢:-)

更新:作为非洲足联在评论中指出,我忘了考虑到信号处理。您必须忽略破损的管道信号,否则write将通过提升该信号而在内部失效。

您可以通过插入这样做:

struct sigaction new_actn, old_actn; 
new_actn.sa_handler = SIG_IGN; 
sigemptyset (&new_actn.sa_mask); 
new_actn.sa_flags = 0; 
sigaction (SIGPIPE, &new_actn, &old_actn); 

开始使用socket函数之前。然后您可以使用:

sigaction (SIGPIPE, &old_actn, NULL); 

恢复以前的信号处理。

+0

看看是否(N <= 0),但在写功能一些发生错误和关闭程序 – SjB 2009-11-25 07:30:22

+0

@SjB,如果'write'返回0,则不* *会产生问题。如果存在临时网络积压,则可能发生这种情况。如果积压成为真正的问题,会话将被关闭,您最终会得到-1。在此之前,继续尝试。 – paxdiablo 2009-11-25 07:35:51

+0

我知道问题。在书写连接中间关闭。例如在500个连接中写入1024个数据并关闭程序 – SjB 2009-11-25 08:10:59

4

套接字编程可能相当棘手,因为您经常不知道直到很晚才发生错误。例如,如果您正在写入的机器异常关闭,则写入调用可能成功(因为您可以写入内部OS缓冲区),只能在关闭调用期间失败。

除非您有验证套接字的应用层方法是活动的(即发送消息并在一段时间内要求响应),否则您无法知道。如果您使用的是标准协议,则可能已经存在处理错误的内容。

所以简短的回答是,你需要检查几乎所有接触套接字(读,写,关闭等)的调用返回的错误。

+2

不幸的是,这是正确的答案。我尝试了几种方法来确定保持活动的HTTP连接是否仍然有效,但它不可靠,没有竞争条件。 – Lothar 2014-04-22 22:41:07

相关问题