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

问题描述

当您读取关闭的 TCP 套接字时,您会收到一个常规错误,即它返回 0 表示 EOF 或 -1 以及 errno 中的错误代码,该代码可以用 perror.

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 To Greg Hewgill 引导我朝着正确的方向思考问题以找到答案.

+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 读取,这可能会被 shell 重定向到管道.例如:

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 在 fork 然后执行这些程序时可能使用 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

发送 SIGHUPinetd 并使用 telnet 连接到端口 8000.这应该导致 inetd 分叉,将套接字复制到 STDINSTDOUTSTDERR 上,然后执行 grep 以 foo 作为参数.如果您开始在 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 上获取命令.有人 telnet 到端口 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 套接字比读一个更糟糕?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-15 16:39