目录

网络中断造成对端无FIN包

操作 read

操作 write

系统崩溃造成对端无FIN包

操作 read

操作 write

对端有FIN包

通过write产生RST,read调用感知RST

向一个已经关闭的连接写,最终导致SIGPIPE

验证数据有效性

1)read、write调用返回值判断

2)设置read超时操作

3)超时处理

4)缓冲区处理


应用层调用send函数后,数据被转发到内核的发送缓冲区中,由协议栈决定什么时候发。当数据发送给对端,对端会反馈ACK,本端的发送套接字缓冲区的相应数据可以删除。

如果发送端没有获取到ACK,不知道对端有没有接收到数据。这种情况怎么处理呢?在应用层增加处理逻辑。

从接收端角度,没有办法保证ACK过的数据可以被应用程序处理。因为数据需要从接收套接字缓冲区拷贝到应用层。如果数据已经存储在接收端的套接字缓冲区中,如果程序被崩溃,这部分数据就丢失了。

数据建立连接后,一种通过read操作,一种是write操作,这个两个操作可以感知异常情况。

网络中断造成对端无FIN包

操作 read

如果采用阻塞读操作,程序无法恢复。  解决方法,read操作设置超时

操作 write

先发送了一段数据流,接下来阻塞在read上。TCP协议栈会不断尝试将发送缓冲区的数据发送出去,再多次失败后,阻塞read上的操作会反馈TIMEOUT的错误信息。

如果此时程序执着地往这条链路上写数据,写操作会失败,并返回SIGPIPE信号给应用程序。

系统崩溃造成对端无FIN包

如系统崩溃,没来得及发送FIN包。崩溃后系统重启,当重传的TCP分组到达重启的系统后,由于系统中没有该TCP分组对应的连接数据,系统会返回RST。

操作 read

如果是阻塞的read调用,会立即反馈一个错误(Connection Reset)

操作 write

如果是write操作,会立即失败,应用程序反馈SIGPIPE信号。

对端有FIN包

可能调用close或shutdown,

可能是对端程序崩溃,操作系统内核代为清理所发出,阻塞的read操作在完成正常结束数据后,FIN包会通过返回EOF,这是内核做的事情。如果应用层不调用read,write 是无法感知的。

通过write产生RST,read调用感知RST

read的返回值为0

向一个已经关闭的连接写,最终导致SIGPIPE

服务器程序被杀死,操作系统会为这个套接字发送FIN包。客户端在收到FIN包后,没有read操作,会继续往这个套接字写入数据。TCP协议,连接是双向的,收到对方的FIN包意味着对方不会再发送任何数据。当数据到达服务器时,操作系统发现内核已经关闭了套接字,会再向客户端发出RST包。对于发送端而言,如果再写,会立即返回一个RST信息。

验证数据有效性

1)read、write调用返回值判断

通过判断EOF,防范程序崩溃。如果服务端同时处理多个客户连接,一般调用shutdown关闭连接的一端

2)设置read超时操作

struct timeval tv;tv.tv_sec=2;tv.tv_usec = 0;setsockopt(connfd,SOL_SOCKET,SO_RECVTIMEO,(const char *)&tv,sizeof tv);while(1)
{int n=recv(connfd,buffer,sizeof(buffer),0);...
}

3)超时处理

for (;;) {readmask = allreads;int rc = select(socket_fd + 1, &readmask, NULL, NULL, &tv);if (rc < 0) {error(1, errno, "select failed");}if (rc == 0) {printf("read timeout\n");...}...
}

select返回0 是超时

4)缓冲区处理

接收数据的缓冲区要能容纳的下所接收的数据

发送的数据内容与内容长度匹配,如果数据长度过长,接收端阻塞,等待数据到来。

减少多次系统调用的开销,举例如下:

//验证收数据的特定字符,先用recv读取多个数据,再依次验证,而不是读一次验证一次
size_t readline(int fd, char *buffer, size_t length) {while (--length> 0) {if (nleft <= 0) {//一次读取过个int nread = recv(fd, read_buffer, sizeof(read_buffer), 0);//异常处理if (nread < 0) {}if (nread == 0)return 0;buffer_pointer = read_buffer;}c = *buffer_pointer++;//验证数据if (c == '\n') {*buffer = '\0';//反馈读取的数据return buffer - buf_first;}}return -1;
}

TCP的“非”可靠性相关推荐

  1. TCP如何保证可靠性

    TCP传输控制协议  TCP 协议是一种面向连接的,为不同主机进程间提供可靠数据传输的协议.TCP 协议假定其所使用的网络栈下层协议(如IP 协议)是非可靠的,其自身提供机制保证数据的可靠性传输.在目 ...

  2. TCP如何实现可靠性传输

    1.UDP与TCP的区别 TCP(TransmissionControl Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流的传输层通信协议. UDP是User Datagram P ...

  3. Q50:TCP如何保证可靠性?

    TCP如何保证可靠性? (1)序列号.确认应答.超时重传 数据到达接收方,接收方需要发出一个确认应答,表示已经收到该数据段,并且确认序号会说明了它下一次需要接收的数据序列号. 如果发送发迟迟未收到确认 ...

  4. TCP如何保证可靠性,TCP如何实现可靠性传输的

    tcp 如何保证可靠性 大家都知道TCP是可靠性传输协议,既然是可靠的,就需要解决比如包丢失了.数据被破坏了.包重复了.乱序了等等这样的问题.下面将从几个方面介绍TCP的可靠性. 1. 校验和 TCP ...

  5. 公开课:TCP协议的可靠性传输机制-王达-专题视频课程

    公开课:TCP协议的可靠性传输机制-11821人已学习 课程介绍         本课程是2015年10月14号晚上在CSDN学院进行的一场公开课,主讲TCP协议的几个方面的传输机制,主要包括以下几个 ...

  6. WIS800C TCP Client 非透传模式连接远程服务器使用方法(转)

    WIS800C TCP Client 非透传模式连接远程服务器使用方法 转载于:https://www.cnblogs.com/LittleTiger/p/11363585.html

  7. 简述tcp协议的可靠性有哪些机制_腾讯面试HTTP与TCP/IP20连问,你能答出多少?

    一.Session 和 cookie 的区别 二.TCP三次握手和四次挥手的流程,断开连接如果只有两次握手,会出现什么. 三.TIME_WAIT 和 CLOSE_WAIT的区别 四.为什么需要 TIM ...

  8. TCP如何保障可靠性

    在TCP的连接中,数据流必须以正确的顺序送达对方.TCP的可靠性是通过顺序编号和确认(ACK)来实现的.TCP在开始传送一个段时,为准备重传而首先将该段插入到发送队列之中,同时启动时钟.其后,如果收到 ...

  9. TCP三次握手和四次挥手?TCP如何保证可靠性?什么是TCP滑动窗口?

    TCP三次握手和四次挥手? 三次握手 tcp3handshake.gif tcp3handshake2.gif tcp3handshake3.gif tcp3handshake4.gif 四次挥手 t ...

最新文章

  1. Alphabet旗下自驾公司Waymo入华,变身“慧摩”!
  2. 你应该知道的五种IO模型
  3. CentOS 7 DIG命令工具打上EDNS补丁
  4. scala调用java代码
  5. 智能门锁半夜离奇开门吓坏用户 官方回应:只是一场误解
  6. aws linux使用ssh登陆_【Linux】 使用ssh连接远程服务器
  7. html代码不安全,安全 – HTML编码是否会阻止各种XSS攻击?
  8. 基于用户画像的商品推荐挑战赛
  9. fread函数在C语言中的用法,c语言fread函数的用法
  10. IOS开发之——数据库-Couchbase(05)
  11. 关于网狐游戏vs2003移植到vs2013
  12. shell 脚本切换用户执行当前脚本命令
  13. 厦门大学计算机学院新院长,厦门大学信息学院对口帮扶座谈会在我院顺利召开...
  14. DTL语言学习(四){% spaceless %}、{% autospace %}和{% verbatim %}标签
  15. linux硬盘识别过程
  16. 集合框架(一)——概述
  17. javascript的几种设计模式
  18. 电赛A题无线运动传感节点总结(一)
  19. RabbitMQ-direct直通模式
  20. 多看Kindle的“导出失败,请检查网络或账号”错误的解决

热门文章

  1. Web服务应用开发(基于J2EE)JavaScript学习
  2. 学习笔记:IDF 移动端UX设计 1.4 响应式设计vs.适应式设计
  3. fatal error C1010: 在查找预编译头时遇到意外的文件结尾。是否忘记了向源中添加“#include stdafx.h”
  4. linux_dma驱动构架分析,s3c6410 linux DMA驱动分析
  5. “元宇宙”基础知识汇总
  6. systemverilog的timescale作用域
  7. 红宝书 第18章整理——XPath
  8. 商品审核网页界面_零杯网页设计大赛赛前讲座
  9. Field stuMapper in com.jc.zj.service.StuServiceImpl required a bean of type ‘com.jc.zj.dao.StuMapper
  10. ArcGIS:加载历史遥感影像