为什么编写一个封闭的TCP套接字比读取一个套接字更糟? [英] Why is writing a closed TCP socket worse than reading one?

查看:74
本文介绍了为什么编写一个封闭的TCP套接字比读取一个套接字更糟?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当您读取一个封闭的TCP套接字时,会得到一个常规错误,即它返回0表示EOF或-1,并且在errno中返回一个错误代码,可以使用

When you read a closed TCP socket you get a regular error, i.e. it either returns 0 indicating EOF or -1 and an error code in errno which can be printed with perror.

但是,当您编写封闭的TCP套接字时,操作系统会将SIGPIPE发送到您的应用程序,如果未捕获到该应用程序,则会终止该应用程序.

However, when you write a closed TCP socket the OS sends SIGPIPE to your app which will terminate the app if not caught.

为什么写关闭的TCP套接字比读它更糟?

Why is writing the closed TCP socket worse than reading it?

推荐答案

+1到

+1 To Greg Hewgill for leading my thought process in the correct direction to find the answer.

在套接字和管道中使用SIGPIPE的真正原因是过滤器惯用语/模式,它适用于Unix系统中的典型I/O.

The real reason for SIGPIPE in both sockets and pipes is the filter idiom / pattern which applies to typical I/O in Unix systems.

从管道开始.诸如grep之类的过滤器程序通常写入STDOUT并从STDIN读取,它们可以由外壳程序重定向到管道.例如:

Starting with pipes. Filter programs like grep typically write to STDOUT and read from STDIN, which may be redirected by the shell to a pipe. For example:

cat someVeryBigFile | grep foo | doSomeThingErrorProne

在分叉然后执行这些程序的shell时,可能使用 dup2 系统调用,将STDINSTDOUTSTDERR重定向到适当的管道.

The shell when it forks and then exec's these programs probably uses the dup2 system call to redirect STDIN, STDOUT and STDERR to the appropriate pipes.

由于过滤器程序grep不知道并且无法知道其输出已被重定向,因此,如果doSomeThingErrorProne崩溃,告诉它停止写入中断管道的唯一方法是发出信号,因为如果已检查,则很少返回对STDOUT的写操作的返回值.

Since the filter program grep doesn't know and has no way of knowing that it's output has been redirected then the only way to tell it to stop writing to a broken pipe if doSomeThingErrorProne crashes is with a signal since return values of writes to STDOUT are rarely if ever checked.

带套接字的模拟将是 inetd 服务器代替外壳

The analog with sockets would be the inetd server taking the place of the shell.

作为示例,我假设您可以将grep转换为通过TCP套接字运行的网络服务.例如,对于inetd,如果要在TCP端口8000上具有grep服务器,则将其添加到/etc/services:

As an example I assume you could turn grep into a network service which operates over TCP sockets. For example with inetd if you want to have a grep server on TCP port 8000 then add this to /etc/services:

grep     8000/tcp   # grep server

然后将其添加到/etc/inetd.conf:

grep  stream tcp nowait root /usr/bin/grep grep foo

SIGHUP发送到inetd并使用telnet连接到端口8000.这将导致inetd派生,将套接字复制到STDINSTDOUTSTDERR上,然后以foo作为参数执行grep.如果您开始在telnet grep中键入行,则会回显包含foo的行.

Send SIGHUP to inetd and connect to port 8000 with telnet. This should cause inetd to fork, dup the socket onto STDIN, STDOUT and STDERR and then exec grep with foo as an argument. If you start typing lines into telnet grep will echo those lines which contain foo.

现在用名为ticker的程序替换telnet,该程序例如将实时股票报价流写入STDOUT并在STDIN上获取命令.有人远程登录到端口8000,然后键入"start java"以获取Sun Microsystems的报价.然后他们起床去吃午餐. telnet莫名其妙地崩溃.如果没有要发送的SIGPIPE,那么ticker会一直保持报价不变,永远不会知道另一端的进程崩溃了,并且不必要地浪费了系统资源.

Now replace telnet with a program named ticker that for instance writes a stream of real time stock quotes to STDOUT and gets commands on STDIN. Someone telnets to port 8000 and types "start java" to get quotes for Sun Microsystems. Then they get up and go to lunch. telnet inexplicably crashes. If there was no SIGPIPE to send then ticker would keep sending quotes forever, never knowing that the process on the other end had crashed, and needlessly wasting system resources.

这篇关于为什么编写一个封闭的TCP套接字比读取一个套接字更糟?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆