应用程序连接服务器时,目的地套接字地址(端口号和IP地址)以参数形式传递给系统调用connect(tcp_v4_connect())。下面逐步介绍初始化该连接
/** * 特殊的路由查找函数,用于TCP。 * 是对普通路由缓存查找函数的封装。 */ static inline int ip_route_connect(struct rtable **rp, u32 dst, u32 src, u32 tos, int oif, u8 protocol, u16 sport, u16 dport, struct sock *sk) { struct flowi fl = { .oif = oif, .nl_u = { .ip4_u = { .daddr = dst, .saddr = src, .tos = tos } }, .proto = protocol, .uli_u = { .ports = { .sport = sport, .dport = dport } } }; int err; if (!dst || !src) { err = __ip_route_output_key(rp, &fl); if (err) return err; fl.fl4_dst = (*rp)->rt_dst; fl.fl4_src = (*rp)->rt_src; ip_rt_put(*rp); *rp = NULL; } return ip_route_output_flow(rp, &fl, sk, 0); }
* 构造并发送SYN段 */ int tcp_connect(struct sock *sk) { struct tcp_sock *tp = tcp_sk(sk); struct sk_buff *buff; tcp_connect_init(sk);/* 初始化传输控制块中与连接相关的成员 */ /* 为SYN段分配报文并进行初始化 */ buff = alloc_skb(MAX_TCP_HEADER + 15, sk->sk_allocation); if (unlikely(buff == NULL)) return -ENOBUFS; /* Reserve space for headers. */ skb_reserve(buff, MAX_TCP_HEADER); TCP_SKB_CB(buff)->flags = TCPCB_FLAG_SYN; TCP_ECN_send_syn(sk, tp, buff); TCP_SKB_CB(buff)->sacked = 0; skb_shinfo(buff)->tso_segs = 1; skb_shinfo(buff)->tso_size = 0; buff->csum = 0; TCP_SKB_CB(buff)->seq = tp->write_seq++; TCP_SKB_CB(buff)->end_seq = tp->write_seq; tp->snd_nxt = tp->write_seq; tp->pushed_seq = tp->write_seq; tcp_ca_init(tp); /* Send it off. */ TCP_SKB_CB(buff)->when = tcp_time_stamp; tp->retrans_stamp = TCP_SKB_CB(buff)->when; /* 将报文添加到发送队列上 */ __skb_queue_tail(&sk->sk_write_queue, buff); sk_charge_skb(sk, buff); tp->packets_out += tcp_skb_pcount(buff); /* 发送SYN段 */ tcp_transmit_skb(sk, skb_clone(buff, GFP_KERNEL)); TCP_INC_STATS(TCP_MIB_ACTIVEOPENS); /* Timer for repeating the SYN until an answer. */ /* 启动重传定时器 */ tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto); return 0; }
/** * TCP和SCTP发送包所用的函数。 * 此函数只接收两个输入参数,所有处理包所需要的信息都可以通过skb直接或者间接的存取。 * Skb: 要传输的包的缓冲区描述符。此数据结构有填入IP报头以及传输包所需要的所有参数(如下一跳网关)。记住,ip_queue_xmit用于处理本地产生的包。转发包没有相关的套接字。 * Ipfragok: 主要由SCTP使用的标志,用来指出是否允许分段。 */ int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
前面阐述啦首次连接设置的处理过程,在此过程缓存了一些重要信息,如路由、设备、APR等。下面将介绍TCP套接着写数据。
报文从套接字到达设备要经历三个阶段:
原文:http://www.cnblogs.com/yuhanghzsd/p/6358735.html