不深挖旁枝末节,以主脉络为主。先记个流水账,旁枝末节的东西用到的时候再挖!
目录
socket fd <—> socket <—> netconn <—> tcp_pcb
函数原型
int lwip_socket(int domain, int type, int protocol)
点1:
返回值,是系统全局数组 sockets (如下)的某个 index(0 <= index < NUM_SOCKETS),即从 0 开始到 NUM_SOCKETS,若 sockets[index] 还未被使用,就将 index 返回。NUM_SOCKETS 的大小可在配置文件中修改。
static struct lwip_sock sockets[NUM_SOCKETS];
点2:
对于TCP, 参数 type = SOCK_STREAM。其他两个参数似乎没什么luan用。
socket fd <—> socket <—> netconn <—> tcp_pcb
(标题:我有点长...)
在应用层调用 lwip_socket() 后,先申请一个 netconn,再申请一个 tcp_pcb,然后在全局的 sockets[] 中找到一个未用的 socket,先将三者绑定在一起,然后返回 socket fd,范围 [ 0,NUM_SOCKETS )。
socket fd 是应用层可以直观看见并操作 socket 的标识,但在 Lwip 内部,对应于 socket fd 有几个外部不能直接访问的重要结构 socket、netconn、tcp_pcb。
看图吧:
每次操作 socket 时,将 socket fd 传入 API, API 内部就会将其作为 index,从全局的 sockets[] 中找到对应的 socket = sockets[index],进而找到对应的 tcp_pcb。
netconn
一个 socket 对应一个 netconn 结构,用于管理当前 socket 所对应的网络连接。
在应用层调用 lwip_socket() 后,内部通过 (struct netconn *)memp_malloc(MEMP_NETCONN) 申请一个 struct netconn 的结构,关于 Lwip memp 我想再用一篇内容分析这个装X的东西,暂且不说。
netconn 申请后,进行一些初始化动作:网络连接类型 NETCONN_TCP、申请 recvmbox(其实就是申请一个固定大小的队列 xQueueCreate(), mbox 大小可配)等。
再然后要申请一个 tcp_pcb。
tcp_pcb
一个 netconn 对应一个 pcb (protocol control block),对于 TCP,就是 tcp_pcb。系统中 tcp_pcb 的个数也是有限的,当第一次申请失败后,会将处于 TIME_WAIT 态时间最长的那个干掉,然后再次尝试申请;如果第二次申请失败后,会将 active 的 && 优先级比当前申请的 pcb 优先级低 && 优先级最低 && 最长时间 inactive 的那个干掉;如果还是申请失败,那就失败吧。
申请成功后,初始化,其中重要的一些:
pcb->snd_buf = TCP_SND_BUF; // 可供发送 data 的空闲空间(字节数)
pcb->rcv_ann_wnd = TCP_WND; // 向对端宣告的 rx window 大小(字节数)
pcb->snd_nxt = iss; // 初始 SN:6510 + tcp_ticks(tcp_ticks 每 500ms 递增1)
pcb->state 就是 [TCP][一] 中所讲的 State-machine 啦! 初始化后默认为 CLOSED。
enum tcp_state {
CLOSED = 0,
LISTEN = 1,
SYN_SENT = 2,
SYN_RCVD = 3,
ESTABLISHED = 4,
FIN_WAIT_1 = 5,
FIN_WAIT_2 = 6,
CLOSE_WAIT = 7,
CLOSING = 8,
LAST_ACK = 9,
TIME_WAIT = 10
};
初始化完成后,注册回调函数:
tcp_recv(pcb, recv_tcp); // rx
tcp_sent(pcb, sent_tcp); // tx
tcp_poll(pcb, poll_tcp, 4); // 周期函数,每 2s 调一次
tcp_err(pcb, err_tcp); // 出错后的回调
做完这些,创建一个 TCP socket 内部的工作基本就做完了哦。
总结
不想写总结。
int socket_fd = lwip_socket(int xxx, SOCK_STREAM, int yyy);
按上面傻瓜式调用,请把 socket_fd 带走不谢。