IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> TCP的“非”可靠性 -> 正文阅读

[系统运维]TCP的“非”可靠性

目录

网络中断造成对端无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;
}

?参考


https://course.0voice.com/v1/course/intro?courseId=2&agentId=0


  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-06-14 22:57:06  更:2022-06-14 23:00:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 15:10:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码