Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C send()始终被EPIPE中断_C_Linux - Fatal编程技术网

C send()始终被EPIPE中断

C send()始终被EPIPE中断,c,linux,C,Linux,我在GNU/Linux下用C编程的多线程服务器中遇到过这种奇怪的行为。当它发送数据时,最终会被SIGPIPE中断。我成功地忽略了send()中的信号,并因此在每个操作之后处理errno 因此,它有两种单独的发送方法,一种是一次发送大量数据(或至少尝试发送),另一种是发送几乎相同数量的数据并将其切成小块。最后,我尝试使用它来保持它发送数据 do { total_bytes_sent += send(client_sd, output_buf + total_bytes_sent,

我在GNU/Linux下用C编程的多线程服务器中遇到过这种奇怪的行为。当它发送数据时,最终会被SIGPIPE中断。我成功地忽略了send()中的信号,并因此在每个操作之后处理errno

因此,它有两种单独的发送方法,一种是一次发送大量数据(或至少尝试发送),另一种是发送几乎相同数量的数据并将其切成小块。最后,我尝试使用它来保持它发送数据

do
{
    total_bytes_sent += send(client_sd, output_buf + total_bytes_sent,
                             output_buf_len - total_bytes_sent, MSG_NOSIGNAL);
}
while ((total_bytes_sent < output_buf_len) && (errno != EPIPE));
do
{
发送的总字节数+=发送(客户端sd,输出字节数+发送的总字节数,
输出\u buf\u len-发送的字节总数,MSG\u NOSIGNAL);
}
while((发送的总字节数<输出字节数)&&(errno!=EPIPE));
这段难看的代码在某些情况下起作用,但并不总是如此

我很确定这不是硬件或ISP的问题,因为这台服务器运行在六台欧洲服务器上,四台在德国,两台在法国

有什么想法吗

提前谢谢

编辑1:是的,我注意到这段代码很糟糕(谢谢Jay)。我最初的意思是,无论客户机是否中断通信,这段代码都会给我一个提示

编辑2:我尝试了一个send(),它随机地给了我同样的错误。这很奇怪,因为我无法发送大数据块。我试图扩大发送缓冲区,但没有成功

编辑3:根据要求,这是一个较大的代码段

data_buf_len = cur_stream->iframe_offset[cur_stream->iframe_num - 1] - first_offset;
data_buf = cur_stream->data;
output_buf = compose_reply(send_params, data_buf, data_buf_len, &output_buf_len);

/* Obviously, time measuring is *highly* unaccurate, only for
 * design consistency purposes (it should return something).
 * */
clock_gettime(CLOCK_REALTIME, &start_time);
total_bytes_sent = send(client_sd, output_buf, output_buf_len, MSG_NOSIGNAL);
clock_gettime(CLOCK_REALTIME, &stop_time);
spent_time = (((int64_t)stop_time.tv_sec * NANOSEC_IN_SEC) +
    (int64_t)stop_time.tv_nsec) - (((int64_t)start_time.tv_sec * NANOSEC_IN_SEC) +
    (int64_t)start_time.tv_nsec);

free(output_buf);
unload_video(cur_video);

if (total_bytes_sent < 0)
{
    log_message(MESSAGE, __func__, IMSG_VIDEOSTOP, cur_video->path);
    log_message(MESSAGE, __func__, IMSG_VIDEOSTOP, NULL);   
}

/* Hope it will not serve >2147483647 seconds (~68 years) of video... */
return ((int)spent_time);
data\u buf\u len=cur\u stream->iframe\u offset[cur\u stream->iframe\u num-1]-第一个\u offset;
数据=当前流->数据;
output_buf=撰写回复(发送参数、数据、数据和输出);
/*很明显,时间测量是非常不精确的,只适用于
*设计一致性目的(它应该返回一些东西)。
* */
时钟获取时间(时钟实时和开始时间);
发送的字节总数=发送(客户端sd、输出buf、输出buf、消息NOSIGNAL);
时钟获取时间(时钟实时和停止时间);
花费的时间=((int64_t)stop_time.tv_sec*纳秒)+
(int64_t)stop_time.tv_nsec)-((int64_t)start_time.tv_sec*纳秒)+
(int64_t)开始时间.tv_nsec);
自由(输出量);
卸载视频(当前视频);
if(发送的总字节数<0)
{
日志消息(消息、函数、IMSG\u视频停止、当前视频->路径);
日志消息(消息,函数,IMSG\u视频停止,空);
}
/*希望它不会提供超过2147483647秒(约68年)的视频*/
返回((int)花费的时间);

只有一个带有大缓冲区的send()调用。还有另一个例子,太大了,无法放在这里,它将每个缓冲区分成更小的块,并为每个块调用send()。

这意味着您正在写入另一端已经关闭的套接字或管道。这是一个应用程序协议错误。

正如EJP所建议的,如果另一方关闭了套接字,EPIPE就会出现。另外,我不认为您将send函数返回的任何内容添加到“total_bytes_sent”中的逻辑是正确的,因为在某些情况下,send可能返回-1,您仍然可以继续操作(例如:在非阻塞套接字的情况下,您可能会在需要重试的地方得到errno EAGAIN)

另外,如果send返回0并且errno不是eppe,那么我猜您将继续循环


编辑:您还可以检查是否正在套接字上调用。即使这样,也会导致这种行为。

如果您使用的是面向流的套接字,例如使用SOCK_stream创建的套接字,则不必成批发送数据

如果输出_buf中有所有可用数据,则只需在阻塞套接字上写入一次

send(客户端、输出、输出、消息)

如果您已经在非阻塞模式下创建了套接字,那么您必须使用select,并且上面的循环是错误的,除了它没有处理Jay指出的返回值-1之外

关于Nos评论:

根据POSIX标准:

发送-通过套接字发送消息

ssize_t send(int套接字、const void*缓冲区、size_t长度、int标志)

如果发送套接字上没有空间容纳要传输的消息,并且套接字文件描述符没有设置O_NONBLOCK,send()将阻塞,直到有空间为止。如果发送套接字上没有空间容纳要传输的消息,并且套接字文件描述符没有设置O_NONBLOCK,send()将失败。select()和poll()函数可用于确定何时可以发送更多数据

因此,只有在发生错误时,send函数调用才会在阻塞套接字上接受整个消息


不幸的是,似乎有些操作系统在发送时返回的字节长度实际上小于字节,即使没有发生错误。这就是W.Richard Stevens使用自己编写的函数的原因。

我明白了。是的,我想这不是个好主意。。。但EPIPE是否会因为我的服务器实现而出现,或者它可能只是客户机的责任?好吧,这只是因为客户机关闭了套接字。但是,同样,您应该明白,是您的逻辑错误没有正确处理对等连接关闭,因此应该在服务器中正确处理。您确定即使客户端没有切断通信,它也会提供EPIPE吗?非常确定,是的,因为我尝试先使用EPIPE条件退出。顺便说一句,可以知道发送缓冲区有多少可用空间吗?是否有内核API或其他什么东西?实际上,我即将启动一个单独的SO线程来讨论阻塞套接字上的发送行为,因为我发现它可能会返回而不发送所有数据,这非常奇怪。