lwip tcp_output_segment源码解析
来源:互联网 发布:精通qt4编程 第2版 编辑:程序博客网 时间:2024/06/05 16:05
原型:
static void
tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
功能:被tcp_output()调用来 发送TCP报文给IP层
实现:
源码如下:
/** * Called by tcp_output() to actually send a TCP segment over IP.被tcp_output()调用,实际的发送TCP报文给IP层 * * @param seg the tcp_seg to send * @param pcb the tcp_pcb for the TCP connection used to send the segment */static voidtcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb){ u16_t len; struct netif *netif; u32_t *opts; /** @bug Exclude retransmitted segments from this count. */ snmp_inc_tcpoutsegs(); /* The TCP header has already been constructed, but the ackno and wnd fields remain.==TCP报头已经构建,但ackno和wnd字段需要保存 */ seg->tcphdr->ackno = htonl(pcb->rcv_nxt); /* advertise our receive window size in this TCP segment==在这个报文段中将要向对方通告我们接受窗口允许大小 */ seg->tcphdr->wnd = htons(pcb->rcv_ann_wnd); /*更新rcv_ann_right_edge 上一次窗口通告时,窗口的右边缘值==rcv_nxt(下一个期望接收到的字节序号)+rcv_ann_wnd*/ pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd; /* Add any requested options. NB MSS option is only set on SYN packets, so ignore it here --MSS选项只当SYN包中设置,所以不再seg结构中体现*/ LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % MEM_ALIGNMENT) == 0); opts = (u32_t *)(void *)(seg->tcphdr + 1);/*+1 为sizeof(*(seg->tcphdr))*/ if (seg->flags & TF_SEG_OPTS_MSS) { TCP_BUILD_MSS_OPTION(*opts);//MSS选项 opts += 1;//u32 }#if LWIP_TCP_TIMESTAMPS pcb->ts_lastacksent = pcb->rcv_nxt; if (seg->flags & TF_SEG_OPTS_TS) { tcp_build_timestamp_option(pcb, opts); opts += 3; }#endif /* Set retransmission timer running if it is not currently enabled This must be set before checking the route.设置重传定时器使能,必须在检查route前设置 */ if (pcb->rtime == -1) { pcb->rtime = 0; } /* If we don't have a local IP address, we get one by calling ip_route().==没有本地IP,获取一个 */ if (ip_addr_isany(&(pcb->local_ip))) { netif = ip_route(&(pcb->remote_ip)); if (netif == NULL) { return; } ip_addr_copy(pcb->local_ip, netif->ip_addr); } if (pcb->rttest == 0) {/*如果要求进行往返时间的估算,初始化相关参数*/ pcb->rttest = tcp_ticks;//RRT估值时,以500ms周期递增 pcb->rtseq = ntohl(seg->tcphdr->seqno);//用于测试RRT报文段序号 LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq)); } LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n", htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) + seg->len)); /*调整报文段pbuf的payload指针,使他指向报文首部*/ len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload); seg->p->len -= len; seg->p->tot_len -= len; seg->p->payload = seg->tcphdr; seg->tcphdr->chksum = 0;#if CHECKSUM_GEN_TCP#if TCP_CHECKSUM_ON_COPY { u32_t acc;#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK u16_t chksum_slow = inet_chksum_pseudo(seg->p, &(pcb->local_ip), &(pcb->remote_ip), IP_PROTO_TCP, seg->p->tot_len);#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ if ((seg->flags & TF_SEG_DATA_CHECKSUMMED) == 0) { LWIP_ASSERT("data included but not checksummed", seg->p->tot_len == (TCPH_HDRLEN(seg->tcphdr) * 4)); } /* rebuild TCP header checksum (TCP header changes for retransmissions!) */ acc = inet_chksum_pseudo_partial(seg->p, &(pcb->local_ip), &(pcb->remote_ip), IP_PROTO_TCP, seg->p->tot_len, TCPH_HDRLEN(seg->tcphdr) * 4); /* add payload checksum */ if (seg->chksum_swapped) { seg->chksum = SWAP_BYTES_IN_WORD(seg->chksum); seg->chksum_swapped = 0; } acc += (u16_t)~(seg->chksum); seg->tcphdr->chksum = FOLD_U32T(acc);#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK if (chksum_slow != seg->tcphdr->chksum) { LWIP_DEBUGF(TCP_DEBUG | LWIP_DBG_LEVEL_WARNING, ("tcp_output_segment: calculated checksum is %"X16_F" instead of %"X16_F"\n", seg->tcphdr->chksum, chksum_slow)); seg->tcphdr->chksum = chksum_slow; }#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */ }#else /* TCP_CHECKSUM_ON_COPY *//*校验和相关*/ seg->tcphdr->chksum = inet_chksum_pseudo(seg->p, &(pcb->local_ip), &(pcb->remote_ip), IP_PROTO_TCP, seg->p->tot_len);#endif /* TCP_CHECKSUM_ON_COPY */#endif /* CHECKSUM_GEN_TCP */ TCP_STATS_INC(tcp.xmit);#if LWIP_NETIF_HWADDRHINT ip_output_hinted(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos, IP_PROTO_TCP, &(pcb->addr_hint));#else /* LWIP_NETIF_HWADDRHINT*/ ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos, IP_PROTO_TCP);//IP层发送接口#endif /* LWIP_NETIF_HWADDRHINT*/}
0 0
- lwip tcp_output_segment源码解析
- lwip tcp_output源码解析
- lwip TCP客户端 tcp_connect函数源码解析
- STM32移植lwip之官方源码解析
- 基于rt-thread+lwip源码分析-LWIP的IP层数据处理代码解析(lwip源码解析二)
- 内存管理pbuf.c源码解析——LwIP学习
- LWIP源码结构分析
- LWIP源码结构分析
- 内存管理pbuf.h头文件源码解析——LwIP学习
- lwip源码分析2----ARP
- lwip源码分析2----ARP
- LwIP源码分析2-ARP
- 基于rt-thread+lwip分析数据是怎么从网卡芯片接收数据到pbuf的(lwip源码解析一)
- LwIP源代码文件目录解析
- LwIP源代码文件目录解析
- LwIP源代码文件目录解析
- lwip
- lwip
- 名字的作用域
- Java中的线程池(1)
- Java 7中的TransferQueue
- 面向对象<6>__笔记(16)
- VS 2010 快捷键
- lwip tcp_output_segment源码解析
- 在使用Eclipse开发大小写快捷键使用问题
- BZOJ 1588: [HNOI2002]营业额统计
- oracle Net manger配置网络服务
- 浅析Android中的消息机制
- Sicily 1128. DICE
- HDOJ 2040 亲和数
- std::sort使用自定义比较函数
- Servlet进阶API--ServletConfig