在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
,那么你现在不能写任何东西(可能是网络积压或其他一些问题,但绝对不是(致命的))。 更新:正如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缓冲区),只能在关闭调用期间失败。
除非你有一个应用层的方式来验证套接字是活动的(即发送一个消息,并要求在一段时间内的回应),你没有办法知道。 如果您使用的是标准协议,则可能已经存在处理错误的东西。
所以简单的答案是,你需要检查几乎每一个接触到套接字(读,写,关闭等)的调用返回的错误。