检查连接是打开还是关闭?(在Linux中的C中)

Saj*_*ani 10 c sockets linux network-programming

在Linux中的套接字编程中我需要在socket中写入数据,但我不知道socket是打开还是关闭.我怎么知道套接字是打开和关闭而没有读取?

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;
}
Run Code Online (Sandbox Code Playgroud)

我从sockfd读到,我确定这个连接是开放的.什么时候在newsockfd写缓冲区我不知道newsockfd是打开还是关闭如何检查newsockfd是否关闭?


我知道问题.在写连接中间关闭.例如,在500连接关闭和程序关闭时写入1024个数据.怎么避免这个?

pax*_*blo 17

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

如果套接字已关闭,您将从中获取-1返回代码write,您可以检查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);
Run Code Online (Sandbox Code Playgroud)

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

sigaction (SIGPIPE, &old_actn, NULL);
Run Code Online (Sandbox Code Playgroud)

恢复以前的信号处理.


Saj*_*ani 14

我使用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;
}
Run Code Online (Sandbox Code Playgroud)

  • 这将起作用,另一种方法是使用`sigaction`忽略`SIGPIPE`(将其处理程序设置为`SIG_IGN`). (2认同)

Chr*_*uin 8

套接字编程可能相当棘手,因为您经常不知道错误发生在很久以后.

例如,如果您要写入的计算机异常关闭,则写入调用可能会成功(因为您可以写入内部OS缓冲区),但只能在关闭调用期间失败.

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

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

  • 不幸的是,这是正确的答案.我尝试了几种方法来确定保持活动的HTTP连接是否仍然有效,但它不可靠且没有竞争条件. (3认同)