SIGPIPE[通俗易懂]

SIGPIPE[通俗易懂]当服务器close一个连接时,若client端接着发数据。根据TCP协议的规定,会收到一个RST响应,client再往这个服务器发送数据时,系统会发出一个SIGPIPE信号给进程,告诉进程这个连接已经断开了,不要再写了。我写了一个服务器程序,在Linux下测试,然后用C++写了客户端用千万级别数量的短链接进行压力测试.  但是服务器总是莫名退出,没有core文件.最后问题确

大家好,又见面了,我是你们的朋友全栈君。

当服务器close一个连接时,若client端接着发数据。根据TCP协议的规定,会收到一个RST响应,client再往这个服务器发送数据时,系统会发出一个SIGPIPE信号给进程,告诉进程这个连接已经断开了,不要再写了。

我写了一个服务器程序,在Linux测试,然后用C++写了客户端用千万级别数量的短链接进行压力测试.  但是服务器总是莫名退出,没有core文件.

最后问题确定为, 对一个对端已经关闭的socket调用两次write, 第二次将会生成SIGPIPE信号, 该信号默认结束进程.

具体的分析可以结合TCP的”四次握手”关闭. TCP是全双工的信道, 可以看作两条单工信道, TCP连接两端的两个端点各负责一条. 当对端调用close时, 虽然本意是关闭整个两条信道, 但本端只是收到FIN包. 按照TCP协议的语义, 表示对端只是关闭了其所负责的那一条单工信道, 仍然可以继续接收数据. 也就是说, 因为TCP协议的限制, 一个端点无法获知对端的socket是调用了close还是shutdown.

对一个已经收到FIN包的socket调用read方法, 如果接收缓冲已空, 则返回0, 这就是常说的表示连接关闭. 但第一次对其调用write方法时, 如果发送缓冲没问题, 会返回正确写入(发送). 但发送的报文会导致对端发送RST报文, 因为对端的socket已经调用了close, 完全关闭, 既不发送, 也不接收数据. 所以, 第二次调用write方法(假设在收到RST之后), 会生成SIGPIPE信号, 导致进程退出.

为了避免进程退出, 可以捕获SIGPIPE信号, 或者忽略它, 给它设置SIG_IGN信号处理函数:

signal(SIGPIPESIG_IGN);

这样, 第二次调用write方法时, 会返回-1, 同时errno置为SIGPIPE. 程序便能知道对端已经关闭.


linux下写socket的程序的时候,如果尝试send到一个disconnected socket上,就会让底层抛出一个SIGPIPE信号。
这个信号的缺省处理方法是退出进程,大多数时候这都不是我们期望的。因此我们需要重载这个信号的处理方法。调用以下代码,即可安全的屏蔽SIGPIPE

signal (SIGPIPE, SIG_IGN);

我的程序产生这个信号的原因是: 
client端通过 pipe 发送信息到server端后,就关闭client端, 这时server端,返回信息给 client 端时就产生Broken pipe 信号了,服务器就会被系统结束了。


对于产生信号,我们可以在产生信号前利用方法 signal(int signum, sighandler_t handler) 设置信号的处理。如果没有调用此方法,系统就会调用默认处理方法:中止程序,显示提示信息(就是我们经常遇到的问题)。我们可以调用系统的处理方法,也可以自定义处理方法。 

系统里边定义了三种处理方法: 
(1)SIG_DFL信号专用的默认动作:
  (a)如果默认动作是暂停线程,则该线程的执行被暂时挂起。当线程暂停期间,发送给线程的任何附加信号都不交付,直到该线程开始执行,但是SIGKILL除外。
  (b)把挂起信号的信号动作设置成SIG_DFL,且其默认动作是忽略信号 (SIGCHLD)。
(2)SIG_IGN忽略信号
  (a)该信号的交付对线程没有影响
  (b)系统不允许把SIGKILL或SIGTOP信号的动作设置为SIG_DFL
3)SIG_ERR   

项目中我调用了signal(SIGPIPESIG_IGN), 这样产生  SIGPIPE 信号时就不会中止程序,直接把这个信号忽略掉。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/139006.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 补码的加减法运算_简述补码减法运算的规则

    补码的加减法运算_简述补码减法运算的规则补码的加减法运算本文内容参考自王达老师的《深入理解计算机网络》一书<中国水利水电出版社>一、补码加法:1、补码的加法运算两个机器数相加的补码可以先通过分别对两个机器数求补码,然后再相加得到,在采用补码形式表示时,进行加法运算可以把符号位和数值位一起进行运算(若符号位有进位,导致了益出,则直接舍弃),结果为两数之和的补码形式。示例1:求两个十进制数的和35+18。首先,规…

    2022年9月13日
    3
  • 工业相机:传感器尺寸与像元尺寸的关系

    工业相机:传感器尺寸与像元尺寸的关系相同分辨率的工业相机,传感器面积越大,则其单位像素的面积也越大,成像质量也会越好。同样的500万像素的工业相机,2/3”的传感器成像质量就要优于1/2”的。一般来说,工业相机的靶面大小,如果要求不是太严格,可以直接按照公式计算。通常,像工业相机厂家会告诉你多少寸的传感器,那么就可以直接使用16mm*X”的传感器得到工业相机的图像传感器的靶面对角线长度。**工业相机使用16mm代表1寸,而不是使用25

    2022年6月9日
    89
  • 代价函数 cost function

    代价函数 cost function代价函数在监督学习的回归问题中,代价函数就是用于找到最优解的目的函数,反应了预测函数的准确性。代价函数的值越小,说明在回归问题的中,计算机程序对数据拟合的越好。也就是假设函数越正确。比如,对于这个假设函数(可以看成是求房价的假设函数):代价函数是:也就是预测值与真实值的差的平方和,再除以2m(2倍样本数量)。在假设函数中:θ0和θ1两个参数,不同的参数会有不同的假设函数如下图

    2022年6月6日
    28
  • 绕id教程_绕id的苹果手机能使用吗

    绕id教程_绕id的苹果手机能使用吗本人在网上购买二手iphone手机。型号6plus,本身有id,无法激活,听说可以绕id,苦血在网上连找三天三夜,终于找到软件,以及方法,现在给大家介绍一下希望能帮到大家同样有id的机油!第一步下载软件,需要软件苹果绕id工具.rar:https://t00y.com/file/9653514-452382356已经打包免费下载!第二步,找一个不小于2gU盘或者内存卡,利用苹果绕id工具.rar:https://t00y.com/file/9653514-452382…

    2022年9月22日
    2
  • 羊车门作业

    羊车门作业

    2021年5月27日
    91
  • wireshark怎么抓包保存_wireshark保存抓包信息

    wireshark怎么抓包保存_wireshark保存抓包信息wireshark抓包使用wireshark抓包分析-抓包实用技巧前言本文整理一下日常抓包使用的一些方法及抓包分析的一些方法。本文基于wireshark2.2.6版本进行抓包处理。其他版本使用方式大同小异。自定义捕获条件wireshark可以将抓包数据保存到硬盘上。若需要长时间抓包的话,需要防止内存过大,因此一般需要指定一定大小切包,释放内存。在捕获-选项菜单中可以设置捕获包的一些配置。输入配置在…

    2025年9月24日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号