RAW网络编程

您所在的位置:网站首页 raw协议打印 RAW网络编程

RAW网络编程

2024-06-28 13:26:17| 来源: 网络整理| 查看: 265

LWIP提供了三种的可以被应用程序直接调用的接口API:

(1)       低水平的,基于内核/回调函数的API(后面称 RAW API)    适用于数据量不大,没有os的MCU

(2)       高水平的,连续的API(后面称LwIP API)                           这种方式最常用,需要os支持,适用于传输数据量大的场合

(3)       BSD风格的套接字API(后面称BSD socket)                       目前还不太稳定

本文介绍的是处于传输层的udp和tcp。两者的区别和各自使用的场合这里就不再赘叙

TCP/IP网络四层模型

 

1.RAW_UDP

(1).udp简介

         端口号表示发送和接收进程, UDP 协议使用端口号为不同的应用保留各自的数据传输通,UDP 和 TCP 协议都是采用端口号对同一时刻内多项应用同时发送和接收数据,而数据接收方则通过目标端口接收数据。有的网络应用只能使用预先为其预留或注册的静态端口;而另外一些网络应用则可以使用未被注册的动态端口。因为 UDP 报头使用两个字节存放端口号,所以端口号的有效范围是从 0 到 65535。一般来说,大于 49151 的端口号都代表动态端口。据报的长度是指包括报头和数据部分在内的总字节数。因为报头的长度是固定的,所以该域主要被用来计算可变长度的数据部分(又称为数据负载)。数据报的最大长度根据操作环境的不同而各异。从理论上说,包含报头在内的数据报的最大长度为 65535 字节。UDP 协议使用报头中的校验和来保证数据的安全 。

 在LWIP中有关处理的函数关系如下:

 

 (2)udp整个通信过程如下图:

(3)其实通讯过程很简单,下面看一下代码 ① 接收函数就是遍历整个pbuf链表,将pbuf的数据存储区域payload里面的数据memcpy到数组里 1 //UDP回调函数 2 void udp_demo_recv(void *arg,struct udp_pcb *upcb,struct pbuf *p, struct ip4_addr *addr,u16_t port) 3 { 4 u32 data_len = 0; 5 struct pbuf *q; 6 if(p!=NULL) //接收到不为空的数据时 7 { 8 memset(udp_demo_recvbuf,0,UDP_DEMO_RX_BUFSIZE); //数据接收缓冲区清零 9 for(q=p;q!=NULL;q=q->next) //遍历完整个pbuf链表 10 { 11 //判断要拷贝到UDP_DEMO_RX_BUFSIZE中的数据是否大于UDP_DEMO_RX_BUFSIZE的剩余空间,如果大于 12 //的话就只拷贝UDP_DEMO_RX_BUFSIZE中剩余长度的数据,否则的话就拷贝所有的数据 13 if(q->len > (UDP_DEMO_RX_BUFSIZE-data_len)) memcpy(udp_demo_recvbuf+data_len,q->payload,(UDP_DEMO_RX_BUFSIZE-data_len));//拷贝数据 14 else memcpy(udp_demo_recvbuf+data_len,q->payload,q->len); 15 data_len += q->len; 16 if(data_len > UDP_DEMO_RX_BUFSIZE) break; //超出TCP客户端接收数组,跳出 17 } 18 upcb->remote_ip=*addr; //记录远程主机的IP地址 19 upcb->remote_port=port; //记录远程主机的端口号 20 udp_demo_flag|=1state=ES_TCPCLIENT_CONNECTED;//状态为连接成功 12 es->pcb=tpcb; 13 es->p=NULL; 14 tcp_arg(tpcb,es); //使用es更新tpcb的callback_arg 15 tcp_recv(tpcb,tcp_client_recv); //初始化LwIP的tcp_recv回调功能 16 tcp_err(tpcb,tcp_client_error); //初始化tcp_err()回调函数 17 tcp_sent(tpcb,tcp_client_sent); //初始化LwIP的tcp_sent回调功能 18 tcp_poll(tpcb,tcp_client_poll,1); //初始化LwIP的tcp_poll回调功能 19 tcp_client_flag|=1state=ES_TCPCLIENT_CLOSING;//需要关闭TCP 连接了 10 es->p=p; 11 ret_err=ERR_OK; 12 }else if(err!= ERR_OK)//当接收到一个非空的数据帧,但是err!=ERR_OK 13 { 14 if(p)pbuf_free(p);//释放接收pbuf 15 ret_err=err; 16 }else if(es->state==ES_TCPCLIENT_CONNECTED) //当处于连接状态时 17 { 18 if(p!=NULL)//当处于连接状态并且接收到的数据不为空时 19 { 20 memset(tcp_client_recvbuf,0,TCP_CLIENT_RX_BUFSIZE); //数据接收缓冲区清零 21 for(q=p;q!=NULL;q=q->next) //遍历完整个pbuf链表 22 { 23 //判断要拷贝到TCP_CLIENT_RX_BUFSIZE中的数据是否大于TCP_CLIENT_RX_BUFSIZE的剩余空间,如果大于 24 //的话就只拷贝TCP_CLIENT_RX_BUFSIZE中剩余长度的数据,否则的话就拷贝所有的数据 25 if(q->len > (TCP_CLIENT_RX_BUFSIZE-data_len)) memcpy(tcp_client_recvbuf+data_len,q->payload,(TCP_CLIENT_RX_BUFSIZE-data_len));//拷贝数据 26 else memcpy(tcp_client_recvbuf+data_len,q->payload,q->len); 27 data_len += q->len; 28 if(data_len > TCP_CLIENT_RX_BUFSIZE) break; //超出TCP客户端接收数组,跳出 29 } 30 tcp_client_flag|=1tot_len);//用于获取接收数据,通知LWIP可以获取更多数据 38 es->p=NULL; 39 pbuf_free(p); //释放内存 40 ret_err=ERR_OK; 41 } 42 return ret_err; 43 } tcp_client_recv

err_t tcp_client_usersent(struct tcp_pcb *tpcb)

和udp一样

1 //LWIP数据发送,用户应用程序调用此函数来发送数据 2 //tpcb:TCP控制块 3 //返回值:0,成功;其他,失败 4 err_t tcp_client_usersent(struct tcp_pcb *tpcb) 5 { 6 err_t ret_err; 7 struct tcp_client_struct *es; 8 es=tpcb->callback_arg; 9 if(es!=NULL) //连接处于空闲可以发送数据 10 { 11 es->p=pbuf_alloc(PBUF_TRANSPORT, strlen((char*)tcp_client_sendbuf),PBUF_POOL); //申请内存 12 pbuf_take(es->p,(char*)tcp_client_sendbuf,strlen((char*)tcp_client_sendbuf)); //将tcp_client_sentbuf[]中的数据拷贝到es->p_tx中 13 tcp_client_senddata(tpcb,es);//将tcp_client_sentbuf[]里面复制给pbuf的数据发送出去 14 tcp_client_flag&=~(1p); //释放内存 16 ret_err=ERR_OK; 17 }else 18 { 19 tcp_abort(tpcb);//终止连接,删除pcb控制块 20 ret_err=ERR_ABRT; 21 } 22 return ret_err; 23 } tcp_client_usersent

err_t tcp_client_poll(void *arg, struct tcp_pcb *tpcb)

 tcp周期性调用的函数,可以用来检测连接状态

//lwIP tcp_poll的回调函数 err_t tcp_client_poll(void *arg, struct tcp_pcb *tpcb) { err_t ret_err; struct tcp_client_struct *es; es=(struct tcp_client_struct*)arg; if(es->state==ES_TCPCLIENT_CLOSING) //连接断开 { debug("poll close\r\n"); tcp_client_connection_close(tpcb,es); //关闭TCP连接 } ret_err=ERR_OK; return ret_err; } tcp_client_poll

err_t tcp_client_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)

检测到远程主机的应答后,发送函数

//lwIP tcp_sent的回调函数(当从远端主机接收到ACK信号后发送数据) err_t tcp_client_sent(void *arg, struct tcp_pcb *tpcb, u16_t len) { struct tcp_client_struct *es; LWIP_UNUSED_ARG(len); es=(struct tcp_client_struct*)arg; if(es->p)tcp_client_senddata(tpcb,es);//发送数据 return ERR_OK; } //此函数用来发送数据 void tcp_client_senddata(struct tcp_pcb *tpcb, struct tcp_client_struct * es) { struct pbuf *ptr; err_t wr_err=ERR_OK; while((wr_err==ERR_OK)&&es->p&&(es->p->lenp; wr_err=tcp_write(tpcb,ptr->payload,ptr->len,1); //将要发送的数据加入到发送缓冲队列中 if(wr_err==ERR_OK) { es->p=ptr->next; //指向下一个pbuf if(es->p)pbuf_ref(es->p); //pbuf的ref加一 pbuf_free(ptr); //释放ptr }else if(wr_err==ERR_MEM)es->p=ptr; tcp_output(tpcb); //将发送缓冲队列中的数据立即发送出去 } } tcp_client_sent

void tcp_client_connection_close(struct tcp_pcb *tpcb, struct tcp_client_struct * es)

删除PCB控制块,将回调函数指向空

1 //关闭与服务器的连接 2 void tcp_client_connection_close(struct tcp_pcb *tpcb, struct tcp_client_struct * es) 3 { 4 //移除回调 5 tcp_abort(tpcb);//终止连接,删除pcb控制块 6 tcp_arg(tpcb,NULL); 7 tcp_recv(tpcb,NULL); 8 tcp_sent(tpcb,NULL); 9 tcp_err(tpcb,NULL); 10 tcp_poll(tpcb,NULL,0); 11 if(es)free(es); 12 tcp_client_flag&=~(1p=NULL; 71 72 tcp_arg(newpcb,Ses); 73 tcp_recv(newpcb,tcp_server_recv); //初始化tcp_recv()的回调函数 74 tcp_err(newpcb,tcp_server_error); //初始化tcp_err()回调函数 75 tcp_poll(newpcb,tcp_server_poll,1); //初始化tcp_poll回调函数 76 tcp_sent(newpcb,tcp_server_sent); //初始化发送回调函数 77 debug("new client connected \r\n"); 78 tcp_server_flag|=1state=ES_TCPSERVER_CLOSING;//需要关闭TCP 连接了 95 Ses->p=p; 96 ret_err=ERR_OK; 97 }else if(err!=ERR_OK) //从客户端接收到一个非空数据,但是由于某种原因err!=ERR_OK 98 { 99 if(p)pbuf_free(p); //释放接收pbuf 100 ret_err=err; 101 }else if(Ses->state==ES_TCPSERVER_ACCEPTED) //处于连接状态 102 { 103 if(p!=NULL) //当处于连接状态并且接收到的数据不为空时将其打印出来 104 { 105 memset(tcp_server_recvbuf,0,TCP_SERVER_RX_BUFSIZE); //数据接收缓冲区清零 106 for(q=p;q!=NULL;q=q->next) //遍历完整个pbuf链表 107 { 108 //判断要拷贝到TCP_SERVER_RX_BUFSIZE中的数据是否大于TCP_SERVER_RX_BUFSIZE的剩余空间,如果大于 109 //的话就只拷贝TCP_SERVER_RX_BUFSIZE中剩余长度的数据,否则的话就拷贝所有的数据 110 if(q->len > (TCP_SERVER_RX_BUFSIZE-data_len)) memcpy(tcp_server_recvbuf+data_len,q->payload,(TCP_SERVER_RX_BUFSIZE-data_len));//拷贝数据 111 else memcpy(tcp_server_recvbuf+data_len,q->payload,q->len); 112 data_len += q->len; 113 if(data_len > TCP_SERVER_RX_BUFSIZE) break; //超出TCP客户端接收数组,跳出 114 } 115 tcp_server_flag|=1tot_len);//用于获取接收数据,通知LWIP可以获取更多数据 123 Ses->p=NULL; 124 pbuf_free(p); //释放内存 125 ret_err=ERR_OK; 126 } 127 return ret_err; 128 129 } 130 //lwIP tcp_err函数的回调函数 131 void tcp_server_error(void *arg,err_t err) 132 { 133 LWIP_UNUSED_ARG(err); 134 debug("tcp error:%x\r\n",(u32)arg); 135 if(arg!=NULL)mem_free(arg);//释放内存 136 } 137 138 139 //LWIP数据发送,用户应用程序调用此函数来发送数据 140 //tpcb:TCP控制块 141 //返回值:0,成功;其他,失败 142 err_t tcp_server_usersent(struct tcp_pcb *tpcb) 143 { 144 err_t ret_err; 145 struct tcp_server_struct *Ses; 146 Ses=tpcb->callback_arg; 147 if(Ses!=NULL) //连接处于空闲可以发送数据 148 { 149 Ses->p=pbuf_alloc(PBUF_TRANSPORT, strlen((char*)tcp_server_sendbuf),PBUF_POOL); //申请内存 150 pbuf_take(Ses->p,(char*)tcp_server_sendbuf,strlen((char*)tcp_server_sendbuf)); //将tcp_server_sentbuf[]中的数据拷贝到Ses->p_tx中 151 tcp_server_senddata(tpcb,Ses); //将tcp_server_sentbuf[]里面复制给pbuf的数据发送出去 152 tcp_server_flag&=~(1p);//释放内存 154 ret_err=ERR_OK; 155 }else 156 { 157 tcp_abort(tpcb);//终止连接,删除pcb控制块 158 ret_err=ERR_ABRT; 159 } 160 return ret_err; 161 } 162 163 164 //lwIP tcp_poll的回调函数 165 err_t tcp_server_poll(void *arg, struct tcp_pcb *tpcb) 166 { 167 err_t ret_err; 168 struct tcp_server_struct *Ses; 169 Ses=(struct tcp_server_struct *)arg; 170 if(Ses->state==ES_TCPSERVER_CLOSING)//需要关闭连接?执行关闭操作 171 { 172 tcp_server_connection_close(tpcb,Ses);//关闭连接 173 } 174 ret_err=ERR_OK; 175 return ret_err; 176 } 177 //lwIP tcp_sent的回调函数(当从远端主机接收到ACK信号后发送数据) 178 err_t tcp_server_sent(void *arg, struct tcp_pcb *tpcb, u16_t len) 179 { 180 struct tcp_server_struct *Ses; 181 LWIP_UNUSED_ARG(len); 182 Ses = (struct tcp_server_struct *) arg; 183 if(Ses->p)tcp_server_senddata(tpcb,Ses);//发送数据 184 return ERR_OK; 185 } 186 //此函数用来发送数据 187 void tcp_server_senddata(struct tcp_pcb *tpcb, struct tcp_server_struct *Ses) 188 { 189 struct pbuf *ptr; 190 u16 plen; 191 err_t wr_err=ERR_OK; 192 while((wr_err==ERR_OK)&&Ses->p&&(Ses->p->lenp; 195 wr_err=tcp_write(tpcb,ptr->payload,ptr->len,1); 196 if(wr_err==ERR_OK) 197 { 198 plen=ptr->len; 199 Ses->p=ptr->next; //指向下一个pbuf 200 if(Ses->p)pbuf_ref(Ses->p); //pbuf的ref加一 201 pbuf_free(ptr); 202 tcp_recved(tpcb,plen); //更新tcp窗口大小 203 }else if(wr_err==ERR_MEM)Ses->p=ptr; 204 tcp_output(tpcb); //将发送缓冲队列中的数据立即发送出去 205 } 206 } 207 208 //关闭tcp连接 209 void tcp_server_connection_close(struct tcp_pcb *tpcb, struct tcp_server_struct *Ses) 210 { 211 tcp_close(tpcb); 212 tcp_arg(tpcb,NULL); 213 tcp_sent(tpcb,NULL); 214 tcp_recv(tpcb,NULL); 215 tcp_err(tpcb,NULL); 216 tcp_poll(tpcb,NULL,0); 217 if(Ses)mem_free(Ses); 218 tcp_server_flag&=~(1


【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭