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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1795193/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 17:56:03  来源:igfitidea点击:

Check connection open or closed ?(in C in Linux)

clinuxsocketsnetwork-programming

提问by Sajad Bahmani

In socket programming in Linux I need to write data in socket but I don't know socket is open or close . how to I know that socket is open and close without read ?

在 Linux 的套接字编程中,我需要在套接字中写入数据,但我不知道套接字是 open 还是 close 。我如何知道套接字在没有读取的情况下打开和关闭?

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

I read from sockfd and I sure this connection is open . When to write buffer in newsockfd I don't know newsockfd is open or close how to check newsockfd is closed ?

我从 sockfd 中读取,并且我确定此连接已打开。什么时候在newsockfd中写入缓冲区我不知道newsockfd是打开还是关闭如何检查newsockfd是否关闭?



I know problem . in middle of writing connection closed . for example write 1024 data in 500 connection closed and program closed. how to avoid this ?

我知道问题。在写连接关闭的中间。例如在 500 个连接关闭和程序关闭时写入 1024 个数据。如何避免这种情况?

采纳答案by Sajad Bahmani

I use send() instead write() that handle no signal :

我使用 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;
}

回答by paxdiablo

The way to check if you can write to a socket is, surprisingly, to try and write to it :-)

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

If the socket has been closed, you will get a -1return code from writeand you can examine errnoto see what the problem was.

如果套接字已关闭,您将得到一个-1返回码write,您可以检查errno问题出在哪里。

If the socket is still valid but you just can't write any data at the moment, writewill return 0. The readcall also behaves in a similar fashion, returning -1if there's a problem.

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

Basically, for write:

基本上,对于write

  • if you get back a -1, there's been a problem and you should check errnoto see if it's recoverable or fatal.
  • If you get back a 0, then you can't write anything at the moment (may be a network backlog or some other problem but definitely not (yet) fatal).
  • If you get a value less that what you wanted, then someof the data has been sent. Adjust your pointers so you can try send the rest in the next cycle. Do notassume a positive return value means the entire block has been sent.
  • If you get back the same number as the number of bytes you tried to send, the entire buffer has been accepted for delivery.
  • If you get back more than what you asked to be sent, send an email off to the kernel developers with some acerbic comment. Linus et al will love that :-)
  • 如果您返回 a -1,则表示存在问题,您应该检查errno它是否可恢复或致命。
  • 如果你得到一个0,那么你现在不能写任何东西(可能是网络积压或其他一些问题,但绝对不是(还)致命的)。
  • 如果你得到的值小于你想要的值,那么一些数据已经被发送。调整您的指针,以便您可以尝试在下一个循环中发送其余的指针。不要承担正收益值意味着整个块已发送。
  • 如果返回的字节数与您尝试发送的字节数相同,则整个缓冲区已被接受进行传送。
  • 如果您收到的回复超出您要求发送的数量,请向内核开发人员发送一封带有尖刻评论的电子邮件。Linus 等人会喜欢的 :-)

Update:As caf has pointed out in the comments, I forgot to take into account the signal handling. You have to ignore the broken pipe signal or writewill fail internally by raising that signal.

更新:正如 caf 在评论中指出的那样,我忘了考虑信号处理。您必须忽略损坏的管道信号,否则write会通过提高该信号而在内部失败。

You can do this by inserting:

您可以通过插入来做到这一点:

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

before starting to use the socket functions. You can then use:

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

sigaction (SIGPIPE, &old_actn, NULL);

to restore the previous signal handling.

恢复之前的信号处理。

回答by Chris Arguin

Socket programming can be rather tricky, because you often don't know an error has occurred until much later.

套接字编程可能相当棘手,因为您通常直到很久以后才知道发生了错误。

For instance, if the machine you are writing to shuts down abnormally, the write call may succeed ( because you were able to write to your internal OS buffers ), only to fail during the close call.

例如,如果您要写入的机器异常关闭,则写入调用可能会成功(因为您能够写入内部操作系统缓冲区),只会在关闭调用期间失败。

Unless you have an application-layer way of verifying the socket is active ( i.e., sending a message and requiring a response within some time period ) you have no way of knowing. If you are using a standard protocol, something may already exist to handle errors.

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

So the short answer is that you need to check for error returns from pretty much every call that touches the socket ( read, write, close, etc... ).

所以简短的回答是,您需要检查几乎每个触及套接字的调用(读取、写入、关闭等)的错误返回。