以下摘抄 Linux内核源码剖析-tcp/ip实现
struct tcp_info {
__u8 tcpi_state; //tcp state: TCP_SYN_SENT,TCP_SYN_RECV,TCP_FIN_WAIT1,TCP_CLOSE etc
__u8 tcpi_ca_state; //congestion state:
__u8 tcpi_retransmits; //重传数,表示当前待重传的包数,这个值在重传完毕后清零
__u8 tcpi_probes; ///* 持续定时器或保活定时器发送且未确认的段数*/
__u8 tcpi_backoff; //用来计算持续定时器的下一个设计值的指数退避算法指数,在传送超时是会递增。
__u8 tcpi_options; //tcp头部选项是否包含:扩展因子、时间戳、MSS等内容
__u8 tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4; //扩展因子数值
__u8 tcpi_delivery_rate_app_limited:1; //限速标志
__u32 tcpi_rto; //重传超时时间,这个和RTT有关系,RTT越大,rto越大
__u32 tcpi_ato; //用来延时确认的估值,单位为微秒.
//在收到TCP报文时,会根据本次与上次接收的时间间隔来调整改制,在设置延迟确认定时器也会根据
//条件修改该值
__u32 tcpi_snd_mss; // 本端的MSS
__u32 tcpi_rcv_mss; // 对端的MSS
__u32 tcpi_unacked; //未确认的数据段数
__u32 tcpi_sacked; //2个含义:server端在listen阶段,可以接收连接的数量;收到的SACK报文数量
__u32 tcpi_lost; //本端在发送出去被丢失的报文数。重传完成后清零
__u32 tcpi_retrans; /* 重传且未确认的数据段数 */
__u32 tcpi_fackets;
/* Times. */
__u32 tcpi_last_data_sent; //当前时间-最近一个包的发送时间,单位是毫秒
__u32 tcpi_last_ack_sent; /* 未使用*/
__u32 tcpi_last_data_recv; //当前时间-最近接收数据包的时间,单位是毫秒
__u32 tcpi_last_ack_recv; //当前时间-最近接收ack的时间,单位是毫秒
/* Metrics. */
__u32 tcpi_pmtu; /* 最后一次更新的路径MTU */
__u32 tcpi_rcv_ssthresh; //当前接收窗口的大小
__u32 tcpi_rtt; //smoothed round trip time,微妙
__u32 tcpi_rttvar; //描述RTT的平均偏差,该值越大,说明RTT抖动越大
__u32 tcpi_snd_ssthresh; //拥塞控制慢开始阈值
__u32 tcpi_snd_cwnd; //拥塞控制窗口大小
__u32 tcpi_advmss; //本端的MSS上限
__u32 tcpi_reordering; /* 没有丢包时,可以重新排序的数据段数 */
__u32 tcpi_rcv_rtt; // 作为接收端,测出的RTT值,单位为微秒. 这个值不是对方计算并传送过来的rtt,而是作为接收端,在没发送数据的情况下
// 通过接收发送端发送的数据的情况计算得到的rtt值。在数据发送方,如果不接受数据,这个值一般情况下为0。
__u32 tcpi_rcv_space; /* 当前接收缓存的大小 */
__u32 tcpi_total_retrans; //统计总重传的包数,持续增长。
__u64 tcpi_pacing_rate; //发送速率
__u64 tcpi_max_pacing_rate; //最大发送速率,默认是unlimited,可以通过SO_MAX_PACING_RATE来设置
__u64 tcpi_bytes_acked; /* RFC4898 tcpEStatsAppHCThruOctetsAcked */
__u64 tcpi_bytes_received; /* RFC4898 tcpEStatsAppHCThruOctetsReceived */
__u32 tcpi_segs_out; /* RFC4898 tcpEStatsPerfSegsOut */
__u32 tcpi_segs_in; /* RFC4898 tcpEStatsPerfSegsIn */
__u32 tcpi_notsent_bytes;
__u32 tcpi_min_rtt;
__u32 tcpi_data_segs_in; /* RFC4898 tcpEStatsDataSegsIn */
__u32 tcpi_data_segs_out; /* RFC4898 tcpEStatsDataSegsOut */
__u64 tcpi_delivery_rate;
__u64 tcpi_busy_time; /* Time (usec) busy sending data */
__u64 tcpi_rwnd_limited; /* Time (usec) limited by receive window */
__u64 tcpi_sndbuf_limited; /* Time (usec) limited by send buffer */
下面来罗列一下判断远端已经断开的方法:
当recv()返回值小于等于0时,socket连接断开。但是还需要判断 errno是否等于 EINTR,如果errno == EINTR 则说明recv函数是由于程序接收到信号后返回的,socket连接还是正常的,不应close掉socket连接。
struct tcp_info info;
int len=size
浏览器打开
查看当前TCP信息 更多字段可以查询/uer/include/netinet/tcp.h文件#include<stdio.h> 2 #include<sys/socket.h> 3 #include<string.h> 4 #include<unistd.h> 5 #include<stdlib.h> 6 #include<...
浏览器打开
当客户端connect端连接上之后,正常通信一会儿,1.客户端断电或者2.断网或者3.关闭fd,服务器怎么检测到客户端已经断开,并且把对应的sockfd 关闭(close(fd))?
1.第一种方法是通过客户端或者服务端开启一个线程不停的发送心跳包,通过心跳包判断客户端存活
2.第二种利用recv和send的返回值和产生的errno来判断tcp连接情况
1、send非阻塞
client/s...
浏览器打开
inet_hashinfo:
这是一个类型为tcp_hashinfo的全局变量,保存当前系统的各种状态的tcp_sock(包括established,listen和bind).
内核初始化调用tcp_init函数时会对该变量进行初始化.结构为:
struct inet_hashinfo {
struct inet_ehash_bucket *ehash; //establ
浏览器打开
当客户端与服务端保持长连接时,客户端除了可以使用心跳包来确认连接状态外,还可以使用一下几种方法:
使用recv() 函数判断
使用recv() 函数的MSG_PEEK选项,使用这个选项可以“偷看(peek)”一下接收队列的数据。所谓“偷看”,就是recv()不从接收队列中把数据移除,因此下一次调用此函数还会接收到此数据。
当TCP连接处于已建立Established状态时,如果接收队列中有数据,recv()函数返回1;如果接收队列中没有数据但是TCP连接没有断开,recv() 函数返回-1,并且把errno
浏览器打开
#include <sys/types.h>
#include <sys/socket.h>
int getsockopt (int s, int level, int optname, void *op...
浏览器打开
Wireshark中常见的TCP Info1. TCP out-of-order segmentTCP存在问题。
Wireshark判断TCP out-of-order是基于TCP包中SEQ number并非期望收到的下一个SEQ number,则判断为out-of-order。因此,出现TCP out-of-order时,很大可能是TCP存在乱序或丢包,导致接收端的seq number不连续。
浏览器打开