LwIP协议栈的学习与应用docx- nxp-lpc(6)

2020-04-14 16:51

conn = netconn_new_with_callback( (protocol == IPPROTO_UDPLITE) ? NETCONN_UDPLITE : NETCONN_UDP, event_callback);

#define netconn_new_with_callback(t, c) netconn_new_with_proto_and_callback(t, 0, c) 简略实现如下: struct netconn*

netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback) {

struct netconn *conn; struct api_msg msg;

conn = netconn_alloc(t, callback); if (conn != NULL ) {

msg.function = do_newconn; msg.msg.msg.n.proto = proto; msg.msg.conn = conn;

TCPIP_APIMSG(&msg); }

return conn; }

主要就看TCPIP_APIMSG了,这个宏有两个定义,一个是LWIP_TCPIP_CORE_LOCKING的,一个非locking的。分别分析这两个不同类型的函数 * Call the lower part of a netconn_* function

* This function has exclusive access to lwIP core code by locking it * before the function is called.

err_t tcpip_apimsg_lock(struct api_msg *apimsg)【这个是可以locking的】 {

LOCK_TCPIP_CORE();

apimsg->function(&(apimsg->msg)); UNLOCK_TCPIP_CORE(); return ERR_OK; }

* Call the lower part of a netconn_* function * This function is then running in the thread context

* of tcpip_thread and has exclusive access to lwIP core code. err_t tcpip_apimsg(struct api_msg *apimsg)【此为非locking的】 {

struct tcpip_msg msg;

21

if (mbox != SYS_MBOX_NULL) { msg.type = TCPIP_MSG_API; msg.msg.apimsg = apimsg; sys_mbox_post(mbox, &msg);

sys_arch_sem_wait(apimsg->msg.conn->op_completed, 0); return ERR_OK; }

return ERR_VAL; }

其实,功能都是一样的,都是要对apimsg->function函数的调用。只是途径不一样而已。看看它们的功能说明就知道了。这么来说apimsg->function的调用很重要了。从netconn_new_with_proto_and_callback函数的实现,可以知道这个function就是do_newconn Void do_newconn(struct api_msg_msg *msg) {

if(msg->conn->pcb.tcp == NULL) { pcb_new(msg); }

/* Else? This \connection already has a PCB allocated. */ /* Is this an error condition? Should it be deleted? */ /* We currently just are happy and return. */

TCPIP_APIMSG_ACK(msg); }

还是看TCP的,在pcb_new函数中有如下代码:

case NETCONN_TCP:

msg->conn->pcb.tcp = tcp_new(); if(msg->conn->pcb.tcp == NULL) { msg->conn->err = ERR_MEM; break; }

setup_tcp(msg->conn); break;

我们知道在这里建立了这个tcp的连接。至于这个超级牛的函数,以后再做介绍。

嗯,还是回过头来接着看accept函数吧。

Sock获得了,接着就是newconn = netconn_accept(sock->conn);通过mbox取

得新的连接。粗略的估计了一下,这个新的连接应该和listen有关系。那就再次打断一下,看看那个listen操作。

lwip_listen --? netconn_listen_with_backlog--? do_listen--?

22

tcp_arg(msg->conn->pcb.tcp, msg->conn);

tcp_accept(msg->conn->pcb.tcp, accept_function);//注册了一个接受函数

* Accept callback function for TCP netconns.

* Allocates a new netconn and posts that to conn->acceptmbox.

static err_t accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) {

struct netconn *newconn; struct netconn *conn;

conn = (struct netconn *)arg;

/* We have to set the callback here even though

* the new socket is unknown. conn->socket is marked as -1. */ newconn = netconn_alloc(conn->type, conn->callback); if (newconn == NULL) { return ERR_MEM; }

newconn->pcb.tcp = newpcb; setup_tcp(newconn); newconn->err = err;

/* Register event with callback */

API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);

if (sys_mbox_trypost(conn->acceptmbox, newconn) != ERR_OK) {

/* When returning != ERR_OK, the connection is aborted in tcp_process(), so do nothing here! */ newconn->pcb.tcp = NULL; netconn_free(newconn); return ERR_MEM; }

return ERR_OK; }

对了,accept函数中从mbox中获取的连接就是这里放进去的。

再回到accept中来,取得了新的连接,接下来就是分配sock了,再然后,再然后?

再然后就等用户来使用接收、发送数据了。

到此整个APP层,也就是传输层以上对socket的封装讲完了。在最后再总结一些整个

路径的调用情况吧

23

API_MSG结构及其实现

如果要评起到最关键作用的一个结构体,那么struct api_msg当之无愧。先看下它的定义: /** This struct contains a function to execute in another thread context and a struct api_msg_msg that serves as an argument for this function. This is passed to tcpip_apimsg to execute functions in tcpip_thread context. */

struct api_msg {

/** function to execute in tcpip_thread context */ void (* function)(struct api_msg_msg *msg); /** arguments for this function */ struct api_msg_msg msg; };

功能说的很清楚。但是具体怎么个操作法还是不知道,没关系,接着看它的调用。

举一个例子,刚好是上一篇中调用,但是没有看具体实现的

err_t netconn_getaddr(struct netconn *conn, struct ip_addr *addr, u16_t *port, u8_t local) {

struct api_msg msg;

msg.function = do_getaddr; msg.msg.conn = conn;

msg.msg.msg.ad.ipaddr = addr; msg.msg.msg.ad.port = port;

24

msg.msg.msg.ad.local = local; TCPIP_APIMSG(&msg);

return conn->err; }

说明一下,api_msg结构几乎都是在netconn_xxx函数中被调用,方式千篇一律,除了msg.funcion的赋值不一样外。上面的调用很简单,对该结构体变量赋值,接着就是调用TCPIP_APIMSG,这个函数上面讲过,可过去看下。既然如此,就不得不说mbox及其相关函数了。 static sys_mbox_t mbox = SYS_MBOX_NULL;【tcp.c】 再看sys_mbox_t的定义,在【src\\include\\lwip\\sys.h】中

/* For a totally minimal and standalone system, we provide null definitions of the sys_ functions. */ typedef u8_t sys_sem_t; typedef u8_t sys_mbox_t; typedef u8_t sys_prot_t;

可以看到这里只是简单的定义成了u8类型,注意上面的红色字体的说明,很明显这个是可移植的一部分,需要根据不同的平台,不同的操作系统具体定义。可以借鉴焦海波大侠的关于ucos上对lwip的移植笔记来看。

我们可以看到在api_msg结构的处理过程中,所有的信息都是包含在api_msg_msg结构体中的,api_msg只是将其和function简单的组合了。下面看下这个牛结构的定义: /** This struct includes everything that is necessary to execute a function for a netconn in another thread context (mainly used to process netconns in the tcpip_thread context to be thread safe). */ struct api_msg_msg {

/** The netconn which to process - always needed: it includes the semaphore

which is used to block the application thread until the function finished. */

struct netconn *conn;

/** Depending on the executed function, one of these union members is used */ union {

/** used for do_send */ struct netbuf *b;

/** used for do_newconn */ struct { u8_t proto; } n;

/** used for do_bind and do_connect */ struct {

struct ip_addr *ipaddr; u16_t port;

25


LwIP协议栈的学习与应用docx- nxp-lpc(6).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:聚四氟乙烯的表面处理与粘接(hao)

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: