<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>idea&#039;s blog &#187; 网络编程</title>
	<atom:link href="http://www.ideawu.net/blog/tag/%e7%bd%91%e7%bb%9c%e7%bc%96%e7%a8%8b/feed" rel="self" type="application/rss+xml" />
	<link>http://www.ideawu.net/blog</link>
	<description>网络服务器架构, Linux C/C++服务器端开发, TCP/IP网络协议, PHP Web后端和Web前端开发, 网站架构.</description>
	<lastBuildDate>Wed, 08 Feb 2012 10:02:48 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>遭遇SIGPIPE</title>
		<link>http://www.ideawu.net/blog/archives/413.html</link>
		<comments>http://www.ideawu.net/blog/archives/413.html#comments</comments>
		<pubDate>Thu, 20 Aug 2009 16:36:57 +0000</pubDate>
		<dc:creator>ideawu</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[网络编程]]></category>

		<guid isPermaLink="false">http://www.ideawu.net/blog/?p=413</guid>
		<description><![CDATA[<p>我写了一个服务器程序, 在Windows下在cygwin环境编译后执行, 然后用C#写了多线程客户端进行压力测试. 程序一直运行正常. 但当在Linux下测试时, 总是莫名退出. 最后跟踪到是write调用导致退出. 用gdb执行程序, 退出时提示&#8221;Broken pipe&#8221;.</p>
<p>最后问题确定为, 对一个对端已经关闭的socket调用两次write, 第二次*可能*会生成SIGPIPE信号, 该信号默认结束进程.</p>
<p>具体的分析可以结合TCP的&#8221;四次握手&#8221;关闭. TCP是全双工的信道, 可以看作两条单工信道, TCP连接两端的两个端点各负责一条. 当对端调用close时, 虽然本意是关闭整个两条信道, 但本端只是收到FIN包. 按照TCP协议的语义, 表示对端只是关闭了其所负责的那一条单工信道, 仍然可以继续接收数据. 也就是说, <strong>因为TCP协议的限制, 一个端点无法获知对端已经完全关闭</strong>.</p>
<p><a href="http://www.ideawu.net/blog/wp-content/uploads/2009/08/tcp_disconnect.jpg"><img src="http://www.ideawu.net/blog/wp-content/uploads/2009/08/tcp_disconnect.jpg" alt="" title="TCP协议&quot;4次握手&quot;关闭" class="alignnone size-full wp-image-414" /></a><br />
截图来自: UNPv1</p>
<p>对一个已经收到FIN包的socket调用read方法, 如果接收缓冲已空, 则返回0, 这就是常说的表示连接关闭. 但第一次对其调用write方法时, 如果发送缓冲没问题, 会返回正确写入(发送). 但发送的报文会导致对端发送RST报文, 因为对端的socket已经调用了close, 完全关闭, 既不发送, 也不接收数据. 所以, 第二次调用write方法(假设在收到RST之后), 会生成SIGPIPE信号, 导致进程退出.</p>
<p>为了避免进程退出, 可以捕获SIGPIPE信号, 或者忽略它, 给它设置SIG_IGN信号处理函数:</p>
<p>signal(SIGPIPE, SIG_IGN);</p>
<p>这样, 第二次调用write方法时, 会返回-1, 同时errno置为SIGPIPE. 程序便能知道对端已经关闭.</p>
<p>PS: Linux下的SIGALRM似乎会每1秒钟往后偏移1毫秒, 但Windows下经过测试完全准时, 不差1毫秒.</p>


<h3>Related posts:</h3><ol><li><a href='http://www.ideawu.net/blog/archives/432.html' rel='bookmark' title='Permanent Link: 如何为Linux生成和打上patch'>如何为Linux生成和打上patch</a></li>
<li><a href='http://www.ideawu.net/blog/archives/135.html' rel='bookmark' title='Permanent Link: 学习Linux有什么立即可见的好处？'>学习Linux有什么立即可见的好处？</a></li>
<li><a href='http://www.ideawu.net/blog/archives/108.html' rel='bookmark' title='Permanent Link: Debian Linux下如何安装软件'>Debian Linux下如何安装软件</a></li>
<li><a href='http://www.ideawu.net/blog/archives/53.html' rel='bookmark' title='Permanent Link: 安装Linux中文输入法fcitx'>安装Linux中文输入法fcitx</a></li>
<li><a href='http://www.ideawu.net/blog/archives/23.html' rel='bookmark' title='Permanent Link: 用Linux生活和学习'>用Linux生活和学习</a></li>
</ol><div><p><img src="http://www.ideawu.net/favicon.ico" /> 你现在看的文章是: <a href="http://www.ideawu.net/blog/archives/413.html" title="遭遇SIGPIPE">遭遇SIGPIPE</a></p>

<div>
	<a href="http://www.benegg.com/linode-ad.php">
		Linode VPS - 美国虚拟主机
	</a>
	|
	<a href="http://www.udpwork.com/">
		IT牛人博客聚合网站
	</a>
</div></div>]]></description>
			<content:encoded><![CDATA[<p>我写了一个服务器程序, 在Windows下在cygwin环境编译后执行, 然后用C#写了多线程客户端进行压力测试. 程序一直运行正常. 但当在Linux下测试时, 总是莫名退出. 最后跟踪到是write调用导致退出. 用gdb执行程序, 退出时提示&#8221;Broken pipe&#8221;.</p>
<p>最后问题确定为, 对一个对端已经关闭的socket调用两次write, 第二次*可能*会生成SIGPIPE信号, 该信号默认结束进程.</p>
<p>具体的分析可以结合TCP的&#8221;四次握手&#8221;关闭. TCP是全双工的信道, 可以看作两条单工信道, TCP连接两端的两个端点各负责一条. 当对端调用close时, 虽然本意是关闭整个两条信道, 但本端只是收到FIN包. 按照TCP协议的语义, 表示对端只是关闭了其所负责的那一条单工信道, 仍然可以继续接收数据. 也就是说, <strong>因为TCP协议的限制, 一个端点无法获知对端已经完全关闭</strong>.</p>
<p><a href="http://www.ideawu.net/blog/wp-content/uploads/2009/08/tcp_disconnect.jpg"><img src="http://www.ideawu.net/blog/wp-content/uploads/2009/08/tcp_disconnect.jpg" alt="" title="TCP协议&quot;4次握手&quot;关闭" class="alignnone size-full wp-image-414" /></a><br />
截图来自: UNPv1</p>
<p>对一个已经收到FIN包的socket调用read方法, 如果接收缓冲已空, 则返回0, 这就是常说的表示连接关闭. 但第一次对其调用write方法时, 如果发送缓冲没问题, 会返回正确写入(发送). 但发送的报文会导致对端发送RST报文, 因为对端的socket已经调用了close, 完全关闭, 既不发送, 也不接收数据. 所以, 第二次调用write方法(假设在收到RST之后), 会生成SIGPIPE信号, 导致进程退出.</p>
<p>为了避免进程退出, 可以捕获SIGPIPE信号, 或者忽略它, 给它设置SIG_IGN信号处理函数:</p>
<p>signal(SIGPIPE, SIG_IGN);</p>
<p>这样, 第二次调用write方法时, 会返回-1, 同时errno置为SIGPIPE. 程序便能知道对端已经关闭.</p>
<p>PS: Linux下的SIGALRM似乎会每1秒钟往后偏移1毫秒, 但Windows下经过测试完全准时, 不差1毫秒.</p>


<h3>Related posts:</h3><ol><li><a href='http://www.ideawu.net/blog/archives/432.html' rel='bookmark' title='Permanent Link: 如何为Linux生成和打上patch'>如何为Linux生成和打上patch</a></li>
<li><a href='http://www.ideawu.net/blog/archives/135.html' rel='bookmark' title='Permanent Link: 学习Linux有什么立即可见的好处？'>学习Linux有什么立即可见的好处？</a></li>
<li><a href='http://www.ideawu.net/blog/archives/108.html' rel='bookmark' title='Permanent Link: Debian Linux下如何安装软件'>Debian Linux下如何安装软件</a></li>
<li><a href='http://www.ideawu.net/blog/archives/53.html' rel='bookmark' title='Permanent Link: 安装Linux中文输入法fcitx'>安装Linux中文输入法fcitx</a></li>
<li><a href='http://www.ideawu.net/blog/archives/23.html' rel='bookmark' title='Permanent Link: 用Linux生活和学习'>用Linux生活和学习</a></li>
</ol><div><p><img src="http://www.ideawu.net/favicon.ico" /> 你现在看的文章是: <a href="http://www.ideawu.net/blog/archives/413.html" title="遭遇SIGPIPE">遭遇SIGPIPE</a></p>

<div>
	<a href="http://www.benegg.com/linode-ad.php">
		Linode VPS - 美国虚拟主机
	</a>
	|
	<a href="http://www.udpwork.com/">
		IT牛人博客聚合网站
	</a>
</div></div>]]></content:encoded>
			<wfw:commentRss>http://www.ideawu.net/blog/archives/413.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

