参考博客:1、参考链接

一、问题来源
Linux上一个TCP服务器负责采集发送图片数据,windows客户端接收数据,当客户端关闭socket或者退出时,服务器进程被强制退出。
二、分析(网络)
具体的分析可以结合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(SIGPIPE, SIG_IGN);
这样, 第二次调用write方法时, 会返回-1, 同时errno置为SIGPIPE. 程序便能知道对端已经关闭.
在linux下写socket的程序的时候,如果尝试send到一个disconnected socket上,就会让底层抛出一个SIGPIPE信号。这个信号的缺省处理方法是退出进程,大多数时候这都不是我们期望的。因此我们需要重载这个信号的处理方法。调用以下代码,即可安全的屏蔽SIGPIPE:
signal (SIGPIPE, SIG_IGN);
系统里边定义了三种处理方法: 
(1)SIG_DFL信号专用的默认动作:
  (a)如果默认动作是暂停线程,则该线程的执行被暂时挂起。当线程暂停期间,发送给线程的任何附加信号都不交付,直到该线程开始执行,但是SIGKILL除外。
  (b)把挂起信号的信号动作设置成SIG_DFL,且其默认动作是忽略信号 (SIGCHLD)。
(2)SIG_IGN忽略信号
  (a)该信号的交付对线程没有影响
  (b)系统不允许把SIGKILL或SIGTOP信号的动作设置为SIG_DFL
(3)SIG_ERR

三、我的用法
1、包含头文件:

#include <signal.h>

2、声明定义一个处理函数

void signal_handler(int sigm);

2、在产生信号产生前调用一下代码:

struct sigaction act;
memset(&act,0,sizeof(act));
// act.sa_handler = SIG_IGN;//设定接受到指定信号后的动作为忽略
act.sa_handler = signal_handler;//设定接受到指定信号后的动作为 相关函数
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction(SIGPIPE,&act,NULL);//屏蔽SIGPIPE信号
sigaction(SIGCHLD,&act,NULL);//屏蔽子进程终结信号,让init进程去处

TCP通信中一方关闭socket,另一方被强制退出(SIGPIPE)相关推荐

  1. TCP通信中服务器处理客户端意外断开

    如果TCP连接被对方正常关闭,也就是说,对方是正确地调用了closesocket(s)或者shutdown(s)的话,那么上面的Recv或Send调用就能马上返回,并且报错.这是由于close soc ...

  2. Tcp通信中服务器处理客户端意外断开!

    所谓意外断开,是客户端(多指支持3G的移动设备)并没有正常关闭socket,双方并未按照协议上的四次挥手去断开连接,一般的处理办法都是利用保活机制.而保活机制分又可以让底层实现也可自己实现. 一.双方 ...

  3. 网络通信-2(TCP通信、ServerSocket、Socket)

    1. TCP通信 UDP中只有发送端和接收端,不区分客户端和服务器端.计算机之间可以任意地发送消息. TCP通信严格区分客户端和服务器. 通信时,必须由客户端去连接服务器才能实现通信.服务器不可主动连 ...

  4. TCP通信中的三次握手与四次挥手

    下图是一次TCP通讯的时序图 TCP通讯时序 在这个例子中,首先客户端主动发起连接.发送请求,然后服务器端响应请求,然后客户端主动关闭连接.两条竖线表示通讯的两端,从上到下表示时间的先后顺序,注意,数 ...

  5. 【Android Protobuf 序列化】Protobuf 服务器与客户端通信 ( TCP 通信中使用 Protobuf )

    文章目录 一.TCP 粘包和分包 二.TCP 粘包和分包解决方案 三.客户端 Android 应用使用 Protobuf 四.服务器端 Java 服务器使用 Protobuf 五.参考资料 一.TCP ...

  6. linux不保存强制退出指令,vi中哪条命令是不保存强制退出_网站服务器运行维护...

    linux中vi查找关键字的方法_网站服务器运行维护 linux中vi查找关键字的方法:进入vi中,先按下"ESC"跳转成命令输入模式,输入斜杠"/",然后输入 ...

  7. java tcp read_【Java TCP/IP Socket】TCP Socket通信中由read返回值造成的的死锁问题(含代码)(转)...

    书上示例 在第一章<基本套接字>中,作者给出了一个TCP Socket通信的例子--反馈服务器,即服务器端直接把从客户端接收到的数据原原本本地反馈回去. 书上客户端代码如下: 书上的服务器 ...

  8. 【Java TCP/IP Socket】TCP Socket通信中由read返回值造成的的死锁问题(含代码)(转)...

    书上示例 在第一章<基本套接字>中,作者给出了一个TCP Socket通信的例子--反馈服务器,即服务器端直接把从客户端接收到的数据原原本本地反馈回去. 书上客户端代码如下: 1 2 3 ...

  9. 2-4:套接字(Socket)编程之TCP通信

    文章目录 一 TCP通信服务端和客户端--和UDP区别 (1)服务端 (2)客户端 二:TCP通信-多进程/线程 (1)多进程版本 (2)多线程版本 (3)线程池版本 一 TCP通信服务端和客户端-- ...

最新文章

  1. 利用Mycat中间件实现RDS MySQL的分库分表及读写分离功能
  2. JavaScript闭包小窥
  3. 类的成员函数与内联以及静态成员
  4. oracle用EXPLAIN PLAN 分析SQL语句
  5. mysql myisam 支持事务吗_第三章(附)mysql表类型MyISAM和InnoDB区别(决定了是否支持事务)...
  6. ETL异构数据源Datax_数据准备_03
  7. linux udp 端口映射,Linux下的UDP/TCP端口映射(netcat and socat)
  8. pyqt5获取显示器的分辨率
  9. EJB 开发环境与入门实例
  10. oracle 函数 如何编写
  11. vue数据双向绑定,Android-MVP模式详解,附超全教程文档
  12. 一个美国人在上海-American McGee
  13. 实验室建立计量管理体系的重要性和意义
  14. p2p与反p2p的博弈,一劳永逸真的不容易么
  15. 2011年6个微博营销趋势
  16. git报错:fatal: 无法为 ‘https‘ 找到远程助手
  17. 1+X 网络系统 建设与运维(中级)实验
  18. 迪杰斯特拉(dijkstra)-两个地铁站最短距离
  19. 微信小程序云开发csv导入数据库中文乱码问题解决
  20. 东东动态夏目猫咪老师404官网html源码

热门文章

  1. 心存美好,总将走过寒冬,春回人间
  2. 输出华氏 摄氏度转换表
  3. 【实战篇】执行计划3种看法,2种操作,4个误区
  4. 【英语六级】【仔细阅读】(3)
  5. 华为设备基本ACL和高级ACL综合配置
  6. 1-4 李宏毅2021春季机器学习教程-PyTorch教学-助教许湛然
  7. 迁出X86架构,你准备好了吗?
  8. java读取OPC DA数据---Utgard
  9. 【Python】PyQT5+爬虫实现简单音乐下载器
  10. 关于角色的转变的思考