检查连接是否打开或closures?(在Linux中的C)

在Linux的套接字编程中,我需要在套接字中写入数据,但是我不知道套接字是打开还是closures。 如何知道socket是打开还是closures而不读取?

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是打开还是closures如何检查newsockfd是closures的?


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

令人惊讶的是,检查你是否可以写入套接字的方法是尝试写入它:-)

如果套接字已关闭,您将从write获得-1返回码,您可以检查errno以查看问题所在。

如果套接字仍然有效,但目前无法写入任何数据,则write将返回0. read调用的行为也类似,如果出现问题,则返回-1

基本上, write

  • 如果你回到-1 ,就有问题,你应该检查errno ,看它是可恢复的还是致命的。
  • 如果你回到0 ,那么你现在不能写任何东西(可能是网络积压或其他一些问题,但绝对不是(致命的))。
  • 如果你得到的价值低于你想要的,那么一些数据已经发送。 调整你的指针,所以你可以尝试在下一个周期发送其余的。 不要假设正的返回值意味着整个块已被发送。
  • 如果返回的数字与您尝试发送的字节数相同,则整个缓冲区已被接受发送。
  • 如果你收回的东西超过了你要发送的内容,请发一封电子邮件给内核开发者一些尖锐的评论。 Linus等人会喜欢:-)

更新:正如caf在评论中指出的,我忘了考虑信号处理。 您必须忽略损坏的管道信号,否则通过提升该信号将导致内部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); 

在开始使用套接字函数之前。 然后你可以使用:

 sigaction (SIGPIPE, &old_actn, NULL); 

恢复以前的信号处理。

我使用send()而不是write()来处理没有信号:

 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; } 

套接字编程可能会相当棘手,因为您经常不知道错误发生的时间要晚得多。

例如,如果您正在写入的机器异常关闭,写入调用可能会成功(因为您可以写入到您的内部OS缓冲区),只能在关闭调用期间失败。

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

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