1. PSH 标志位

PSH 标志位TCP6个标志位中重要的一个标志。它的英文单词是 PUSH,表示“推”的意思。
了解它的作用需要首先了解缓冲区。

1.1 接收缓冲区和发送缓冲区

在谈 PSH 标志位前,先来说说 TCP 双方是如何发送数据的。

假设有发送方 A 和接收方 B。发送方有一个发送缓冲区,接收方有一个接收缓冲区,见图 1。进程 A 发送”hello”, “world” 后,只是将这些数据写到自己的发送缓冲区,为了能讲清 PSH 的作用,不妨假设我们可以自己指定 PSH 标志。在图 1 所示的情况中,第一次 write 没有指定 PSH 标记,而第二次指定了 PSH 标志。

图1 TCP 协议中的发送缓冲区与接收缓冲区

接收进程 B,接收到 TCP 报文后,将数据放入到接收缓冲区。

1.2 PSH 的作用

在 1.1 节中,TCP 模块什么时候将数据发送出去(从发送缓冲区中取数据),以及 read 函数什么时候将数据从接收缓冲区读取都是未知的。

如果使用 PSH 标志,上面这件事就确认下来了:

对于发送方来说,由 TCP 模块自行决定,何时将接收缓冲区中的数据打包成 TCP 报文,并加上 PSH 标志(在图 1 中,为了演示,我们假设人为的干涉了 PSH 标志位)。一般来说,每一次 write,都会将这一次的数据打包成一个或多个 TCP 报文段(如果数据量大于 MSS 的话,就会被打包成多个 TCP 段),并将最后一个 TCP 报文段标记为 PSH。

当然上面说的只是一般的情况,如果发送缓冲区满了,TCP 同样会将发送缓冲区中的所有数据打包发送。

如果接收方接收到了某个 TCP 报文段包含了 PSH 标志,则立即将缓冲区中的所有数据推送给应用进程(read 函数返回)。

当然有时候接收缓冲区满了,也会推送。

2.实验-使用client-server 程序验证PSH的作用

实验概述:我们使用一个简单的回射服务器来完成这个实验,客户端将发送一个8196字节的包给服务器端。

文件1:str_cli.h

void str_cli(FILE *fp, int sockfd);

文件2:common.h

ssize_t  readn(int fd, void *vptr, size_t n);
ssize_t  writen(int fd, const void *vptr, size_t n);
ssize_t  readline(int fd, void *vptr, size_t maxlen);

文件3:client.cpp

#include <stdio.h>
#include <strings.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "str_cli.h"
#include <arpa/inet.h>
#include "common.h"void
str_cli(FILE *fp, int sockfd)
{char    sendline[8196], recvline[4096];for(int i = 0;i < 8195; i++){sendline[i] = 'a';}sendline[8196] = '\0';printf("sendline is %s",sendline);/*while(fgets(sendline, 4096, fp) != NULL){writen(sockfd, sendline, strlen(sendline));if(readline(sockfd, recvline, 4096) == 0){printf("str_cli: server terminated prematurely");exit(0);}fputs(recvline, stdout);}*/writen(sockfd,sendline,strlen(sendline));if(readline(sockfd, recvline, 4096) == 0){printf("str_cli: server terminated prematurely");exit(0);}fputs(recvline,stdout);}int
main(int argc, char **argv)
{int                   sockfd;struct sockaddr_in    servaddr;if(argc != 2){printf("usage: tcpcli <IPaddress> ");exit(0);}if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){perror("socket");exit(1);}bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(9877);if(inet_pton(AF_INET, argv[1], &servaddr.sin_addr) < 0){perror("inet_pton");    exit(1);}if(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0){perror("connect");exit(1);}str_cli(stdin, sockfd);    /* do it all */exit(0);
}

文件4:server.cpp

#include <sys/socket.h>
#include <strings.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include "common.h"
#include <unistd.h>
#include<signal.h>
#include<wait.h>void
str_echo(int sockfd)
{ssize_t        n;char           buf[4096];
again:while((n = read(sockfd, buf, 4096)) > 0)writen(sockfd, buf, n);if(n < 0 && errno == EINTR)goto again;else if(n < 0){perror("read");exit(1);}}int main(int argc,char **argv)
{int                 listenfd,connfd;pid_t               childpid;socklen_t           clilen;struct sockaddr_in  cliaddr,servaddr;if((listenfd = socket(AF_INET,SOCK_STREAM,0)) < 0){perror("socket");exit(1);}bzero(&servaddr,sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(9877);if(bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) < 0){perror("bind");exit(1);}if(listen(listenfd,5) < 0){perror("listen");exit(1);}for(;;){clilen = sizeof(cliaddr);if((connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen)) < 0){if(errno = EINTR)continue;else{perror("accept");exit(1);}      }if((childpid = fork()) < 0){perror("fork");exit(1);}else if(childpid == 0){if(close(listenfd) < 0){perror("child close");exit(1);}str_echo(connfd);exit(0);}if(close(connfd) < 0){perror("parent close");exit(1);}}}

运行服务器端程序,使用客户端发送数据包。同时在客户端上使用tcpdump 抓取数据包。

使用wireshark工具,分析tcpdump抓取到的包,我们在client端的程序中,一次性发送了8196字节的数据,受传输MTU的限制,被拆成了6个包进行发送。其中前5个包没有PSH标志,最后1个包有PSH标志。
当服务收到前5个包时,不会理解交付给应用程序(即read函数不会返回),直到最后1个置了PSH包到达server端时,交付给应用进程,这个时候read函数返回。
PS:在抓包过程中如果出现了包的大小大于MTU的情况,主要是由于网卡tso属性导致的。
可以参考这篇文章进行处理
为什么TCP/IP包长会大于MTU?.

参考文章

https://blog.csdn.net/weixin_33686714/article/details/91848168

TCP 协议标志位PSH的作用相关推荐

  1. TCP协议详解之TCP Flag标志位来判断TCP会话的开始和结束

    首先回顾一下TCP标志位的具体含义. TCP Flag标志位(控制位) 一个TCP包的详细内容: TCP FLAG 标记占1.5个byte,12bit(4bit+8bit,前半个byte与Header ...

  2. TCP协议中的PSH和URG标志位

    TCP段格式 源端口 数据发送方的端口号,2个字节 目的端口 数据接受方的端口,2个字节 序号 报文段序号,数据报文中第一个字节的序号.4个字节,共2的32次方个序列号. 确认序号 也是4个字节,是期 ...

  3. TCP/IP 标志位 SYN ACK RST UTG PSH FIN

    三次握手:发送端发送一个SYN=1,ACK=0标志的数据包给接收端,请求进行连接,这是第一次握手:接收端收到请求并且允许连接的话,就会发送一个 SYN=1,ACK=1标志的数据包给发送端,告诉它,可以 ...

  4. TCP Flags标志位介绍

          传输控制协议(Transmission Control Protocol,TCP)是一种传输层协议.TCP使数据包从源到目的地的传输更加顺畅.它是一种面向连接的端到端协议.每个数据包由TC ...

  5. 4-1:TCP协议之传输层的作用及传输层协议TCP和UDP

    文章目录 一:传输层的定义 二:通信处理 三:传输层协议 四:TCP协议的可靠和性能 一:传输层的定义 前面说过,IP首部有一个协议字段用于标识网络层(IP)的上一层采用哪一种传输层协议.根据这个字段 ...

  6. TCP报文标志位--URG,PSH调研

    1.URG:紧急位 当设置为1时,表示TCP报文中的紧急指针有效,此时告诉系统此报文段中有紧急数据,应优先传送,发送方会把紧急数据放至报文最前面,URG设置为0时,紧急指针无意义: 窗口大小为0时,也 ...

  7. URG和PSH标志位

    TCP报文中共有6个标志位. URG:紧急标志位 ACK:确认标志位 PSH:推送标志位 RST:复位标志位 SYN:同步标志位 FIN:结束标志位     URG:紧急标志位,它使一端可以告诉另一端 ...

  8. 网络:传输层之TCP协议

    目录 一.概述 1.主要特点 2.TCP的连接 二.TCP的首部 三.可靠传输 1.停止等待协议 1.1 协议描述 1.2 故障处理 1.3 超时定时器 1.4 优缺点 2.连续ARQ协议 2.1 协 ...

  9. [linux] Linux网络之TCP协议详解

    目录 1. 传输层 2. 端口号 3. TCP协议 3.1 TCP协议的特性 3.1.1 面向连接 3.1.2 可靠传输 3.1.3 面向字节流 3.2 TCP报头 3.3 TCP连接管理及可靠性问题 ...

最新文章

  1. 一文搞懂PointNet全家桶——强势的点云处理神经网络
  2. linux7提示软件安装源位置不对,详解 RHEL7.1 yum源配置与软件安装
  3. 德勤:2025年汽车行业价值链的四个合理情境
  4. liunx之tar 命令
  5. 向朋友借钱:文章值得一读,让人思索良久
  6. 2020年9月14日运行代码总结
  7. 13c语言中的文件是一种流式文件,读写时均以字符为单位.,C语言判断题部分.doc...
  8. Tomcat Maven插件分环境运行配置
  9. Qt5调用Snap7
  10. Yate架构分析概要
  11. 画业务逻辑流程图后的感想
  12. 【博客431】接入层 汇聚层 核心层
  13. 计算机函数公式大全ppt,三角函数公式大全分解.ppt
  14. 如何将dataframe数据类型某两列合并成一列
  15. 做私域最常犯的四个错误
  16. “已成功与服务器建立连接,但是在登录过程中发生错误“的解决方法
  17. 迷你挑状告京东20元转让80%股权
  18. 聚类算法中 K均值聚类(KMeans)的python实现
  19. 多少岁才能评中级工程师,需要工作业绩吗,需要几个工作业绩?
  20. kaptcha html页面验证码,kaptcha验证码使用配置

热门文章

  1. 教你如何解决vue跨域问题(vue cli3)
  2. 《经典诗文诵读的实践与研究》中期报告
  3. linux下如何压缩文件夹加密,linux下的文件/文件夹压缩加密方法
  4. 海康web无插件开发实现4*3窗口布局
  5. html如何做本地链接,如何创建本地连接,小编教你电脑如何创建本地连接
  6. linux 设置 java.library.path,Linux下修改java.library.path-Go语言中文社区
  7. Android 气泡动画(自定义View类)
  8. 直播APP服务器用什么配置
  9. 南京大专计算机考试成绩查询入口,南京高考成绩查询系统入口
  10. python爬qq空间_QQ空间动态爬虫