标签:
1 int
2 lwip_recv(int s, void *mem, size_t len, int flags)
3 {
4 return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
5 }
1 int
2 lwip_recvfrom(int s, void *mem, size_t len, int flags,
3 struct sockaddr *from, socklen_t *fromlen)
4 {
5 .............
6 do{
7 .............
8 sock->lastdata = buf = netconn_recv(sock->conn); // 专属socket->conn
9 .............
10 }
11 }
1 /**
2 * Receive data (in form of a netbuf containing a packet buffer) from a netconn
3 *
4 * @param conn the netconn from which to receive data
5 * @return a new netbuf containing received data or NULL on memory error or timeout
6 */
7 struct netbuf *
8 netconn_recv(struct netconn *conn)
9 {
10 .............
11 if (sys_arch_mbox_fetch(conn->recvmbox, (void *)&p, conn->recv_timeout)==SYS_ARCH_TIMEOUT) { // 可见recv()函数实际上是从专属sock->conn->recvmbox上取数据。
12 memp_free(MEMP_NETBUF, buf);
13 conn->err = ERR_TIMEOUT;
14 return NULL;
15 }
16 ..............
17 }
1 void
2 tcp_input(struct pbuf *p, struct netif *inp)
3 {
4 ........
5 for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { // 当client端发TCP segment过来时,根据client端和server端的ip地址和port号,显然在active pcbs链表里可以找到对应的pcb,这也是一个此client专属的pcb
6 LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
7 LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
8 LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
9 if (pcb->remote_port == tcphdr->src &&
10 pcb->local_port == tcphdr->dest &&
11 ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
12 ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
13
14 /* Move this PCB to the front of the list so that subsequent
15 lookups will be faster (we exploit locality in TCP segment
16 arrivals). */
17 LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb);
18 if (prev != NULL) {
19 prev->next = pcb->next;
20 pcb->next = tcp_active_pcbs;
21 tcp_active_pcbs = pcb;
22 }
23 LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb);
24 break;
25 }
26 prev = pcb;
27 }
28 .........
29 err = tcp_process(pcb); //我们之前分析过的函数
30 .........
31 if (err != ERR_ABRT) {
32 if (recv_flags & TF_RESET) {
33 /* TF_RESET means that the connection was reset by the other
34 end. We then call the error callback to inform the
35 application that the connection is dead before we
36 deallocate the PCB. */
37 TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST);
38 tcp_pcb_remove(&tcp_active_pcbs, pcb);
39 memp_free(MEMP_TCP_PCB, pcb);
40 } else if (recv_flags & TF_CLOSED) {
41 /* The connection has been closed and we will deallocate the
42 PCB. */
43 tcp_pcb_remove(&tcp_active_pcbs, pcb);
44 memp_free(MEMP_TCP_PCB, pcb);
45 } else {
46 err = ERR_OK;
47 /* If the application has registered a "sent" function to be
48 called when new send buffer space is available, we call it
49 now. */
50 if (pcb->acked > 0) {
51 TCP_EVENT_SENT(pcb, pcb->acked, err);
52 }
53
54 if (recv_data != NULL) {
55 if(flags & TCP_PSH) {
56 recv_data->flags |= PBUF_FLAG_PUSH;
57 }
58
59 /* Notify application that data has been received. */
60 TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err); // 这里把接收到的数据recv_data通过这个宏进行处理,实际上是调用了函数recv_tcp()
61
62 ...............
63 }
64 }
65 }
66 ..............
67 }
1 /**
2 * Receive callback function for TCP netconns.
3 * Posts the packet to conn->recvmbox, but doesn‘t delete it on errors.
4 *
5 * @see tcp.h (struct tcp_pcb.recv) for parameters and return value
6 */
7 static err_t
8 recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) // 注意这里的pcb是client专属pcb,p就是上面的recv_data,指向TCP层收到并处理好的数据
9 {
10 struct netconn *conn;
11 u16_t len;
12
13 LWIP_UNUSED_ARG(pcb);
14 LWIP_ASSERT("recv_tcp must have a pcb argument", pcb != NULL);
15 LWIP_ASSERT("recv_tcp must have an argument", arg != NULL);
16 conn = arg; // 这个arg就是专属pcb->conn,也是client专属的conn
17 LWIP_ASSERT("recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb);
18
19 if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL)) {
20 return ERR_VAL;
21 }
22
23 conn->err = err;
24 if (p != NULL) {
25 len = p->tot_len;
26 SYS_ARCH_INC(conn->recv_avail, len);
27 } else {
28 len = 0;
29 }
30
31 if (sys_mbox_trypost(conn->recvmbox, p) != ERR_OK) { // 原来如此!这里把p指向的数据最终挂到了专属pcb->conn的recvmbox上,而取走它的就是上文分析的lwip_recv()函数,lwip_recv()函数通过新socket号来到这个recvmbox上取
32 return ERR_MEM;
33 } else {
34 /* Register event with callback */
35 API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
36 }
37
38 return ERR_OK;
39 }
标签:
原文地址:http://www.cnblogs.com/codingfun/p/4187570.html