两个重要数据结构的比较和分析:
struct socket {
//当前套接字的类型,如SOCK_STREAM,SOCK_DGRAM和SOCK_RAW
short type; /* SOCK_STREAM, ... */
//套接字的当前状态存储在state中,最重要的状态是SS_CONECTING,SS_CONNECTED
socket_state state;
//标志位
long flags;
//INET 地址系统中的套接字指针ops指向操作inet_proto_ops或者unix_proto_ops
struct proto_ops *ops; /* protocols do most everything */
void *data; /* protocol data经常在ops操作中强制转换层sock结构*/
//远端服务器套接字链接到服务器端
struct socket *conn; /* server socket connected to */
//只用于服务器端,表示等待连接但尚未完成连接的客户端socket结构链表
struct socket *iconn; /* incomplete client conn.s */
//指向下个socket结构
struct socket *next;
//指向等待队列
struct wait_queue **wait; /* ptr to place to wait on */
struct inode *inode;
//如果进程选择了文件异步处理,那需要将事件通知到所有到所有的进程。处于这个原因,
这些进程需要被保存在fasync_list中
struct fasync_struct *fasync_list; /* Asynchronous wake up list */
};
/*
* This structure really needs to be cleaned up.
* Most of it is for TCP, and not used by any of
* the other protocols.
*/
struct sock {
//ip选项缓存于此处
struct options *opt;
//当前写缓存区大小
volatile unsigned long wmem_alloc;
//当前读缓存区大小
volatile unsigned long rmem_alloc;
//表示应用程序下一次写数据时对应的第一个字节的序列号
unsigned long write_seq;
//表示本地将要发送的下一个数据包中第一个字节对应的序列号
unsigned long sent_seq;
//表示本地希望从远端接受的下一个数据的序列号
unsigned long acked_seq;
//应用程序有待读取数据的一个序列号
unsigned long copied_seq;
//表示目前本地接收的对本地发送数据的应答序列号
unsigned long rcv_ack_seq;
/*窗口大小,是一个绝对值,表示本地将要发生数据包中所包含最后一个数据的序列号不可大于window_seq.window_seq初始化为send_seq加上远端当前通报的窗口大小,这个窗口大小由TCP 首部字段指定的。*/
unsigned long window_seq;
//fin_seq对方发送FIN数据包使用
unsigned long fin_seq;
//下面两个字段用于紧急处理,urg_seq表示紧急数据最大序列
unsigned long urg_seq;
//标志位,但设置为1时,表示接收到紧急数据
unsigned long urg_data;
/*
* Not all are volatile, but some are, so we
* might as well say they all are.
*/
volatile char inuse,//但inuse=1表示其他进程正在使用该sock结构,本进程需要等待
dead, //dead =1表示该sock结构处于释放状态
urginline, // urginline =1表示紧急数据将被当作普通数据处理
intr,
blog, //blog=1表示对应套接字处于节制状态,此时接收的数据全被丢弃
done,
reuse,
keepopen, //keepopen=1表示使用保活定时器
linger, //linger=1表示关闭套接字时需要等待一段时间确认其关闭
delay_acks, //delay_acks=1 表示延迟应答,可1次对多个数据进行应答
destroy, //destroy=1 表示该sock 等待销毁
ack_timed, //
no_check,
zapped, /* In ax25 & ipx means not linked 在IpX中被使用作连接标志 */
broadcast,
nonagle;//nonagle=1表示不使用Nagle算法,Nagle算法是在一个发送的数据包被应答之前,不可再继续发送其他数据包,
unsigned long lingertime;//表示等待关闭操作的时间,linger=-1才有意义
int proc; //该sock所属的进程
//以下3个字段属于sock连接
struct sock *next;
struct sock *prev; /* Doubly linked chain.. */
struct sock *pair;
//send_head,send_tail用于TCP协议重发队列
struct sk_buff * volatile send_head;
struct sk_buff * volatile send_tail;
//接收数据包缓存队列
struct sk_buff_head back_log;
// partial用于创建最大长度的待发送数据包
struct sk_buff *partial;
//partial_timer 定时器用于按时发送partical指针的数据包,以免缓存时间过长
struct timer_list partial_timer;
//重发次数
long retransmits;
//待发送的数据包
struct sk_buff_head write_queue,
receive_queue;
struct proto *prot;
struct wait_queue **sleep;
unsigned long daddr;
unsigned long saddr;
unsigned short max_unacked;
unsigned short window;
unsigned short bytes_rcv;
/* mss is min(mtu, max_window) */
unsigned short mtu; /* mss negotiated in the syn's */
volatile unsigned short mss; /* current eff. mss - can change */
volatile unsigned short user_mss; /* mss requested by user in ioctl */
volatile unsigned short max_window;
unsigned long window_clamp;
unsigned short num;
volatile unsigned short cong_window;
volatile unsigned short cong_count;
volatile unsigned short ssthresh;
volatile unsigned short packets_out;
volatile unsigned short shutdown;
volatile unsigned long rtt;
volatile unsigned long mdev;
volatile unsigned long rto;
/* currently backoff isn't used, but I'm maintaining it in case
* we want to go back to a backoff formula that needs it
*/
volatile unsigned short backoff;
volatile short err;
unsigned char protocol;
volatile unsigned char state;
volatile unsigned char ack_backlog;
unsigned char max_ack_backlog;
unsigned char priority;
unsigned char debug;
unsigned short rcvbuf;
unsigned short sndbuf;
unsigned short type;
unsigned char localroute; /* Route locally only */
#ifdef CONFIG_IPX
ipx_address ipx_dest_addr;
ipx_interface *ipx_intrfc;
unsigned short ipx_port;
unsigned short ipx_type;
#endif
#ifdef CONFIG_AX25
/* Really we want to add a per protocol private area */
ax25_address ax25_source_addr,ax25_dest_addr;
struct sk_buff *volatile ax25_retxq[8];
char ax25_state,ax25_vs,ax25_vr,ax25_lastrxnr,ax25_lasttxnr;
char ax25_condition;
char ax25_retxcnt;
char ax25_xx;
char ax25_retxqi;
char ax25_rrtimer;
char ax25_timer;
unsigned char ax25_n2;
unsigned short ax25_t1,ax25_t2,ax25_t3;
ax25_digi *ax25_digipeat;
#endif
#ifdef CONFIG_ATALK
struct atalk_sock at;
#endif
/* IP 'private area' or will be eventually */
int ip_ttl; /* TTL setting */
int ip_tos; /* TOS */
struct tcphdr dummy_th;
struct timer_list keepalive_timer; /* TCP keepalive hack */
struct timer_list retransmit_timer; /* TCP retransmit timer */
struct timer_list ack_timer; /* TCP delayed ack timer */
int ip_xmit_timeout; /* Why the timeout is running */
#ifdef CONFIG_IP_MULTICAST
int ip_mc_ttl; /* Multicasting TTL */
int ip_mc_loop; /* Loopback (not implemented yet) */
char ip_mc_name[MAX_ADDR_LEN]; /* Multicast device name */
struct ip_mc_socklist *ip_mc_list; /* Group array */
#endif
/* This part is used for the timeout functions (timer.c). */
int timeout; /* What are we waiting for? */
struct timer_list timer; /* This is the TIME_WAIT/receive timer when we are doing IP */
struct timeval stamp;
/* identd */
struct socket *socket;
/* Callbacks */
void (*state_change)(struct sock *sk);
void (*data_ready)(struct sock *sk,int bytes);
void (*write_space)(struct sock *sk);
void (*error_report)(struct sock *sk);
};