uIP是否可用于串口转以太网模块?

[复制链接]
6417|16
 楼主| BitFu 发表于 2013-3-7 11:30 | 显示全部楼层 |阅读模式
翻了一二姨家的帖子发现:
uip如果做为tcp服务器端向客户端发送数据只有三种方法
1.在收到新数据时进行发送
2.在需要重发时进行发送
3.在收到对方收到数据的ack确认后,如果有数据可以进行发送
这是否意味着uIP无法随机的主动发送数据到已连接的客户端?
因为实现串口转以太网模块需要实时的将串口收到的数据发送给TCP客户端的。
dirtwillfly 发表于 2013-3-7 11:44 | 显示全部楼层
在收到新数据时进行发送不行吗?这不就是实时吗
少先队员 发表于 2013-3-7 17:24 | 显示全部楼层
好像 应该 我记得 差不多可以主动发啊
 楼主| BitFu 发表于 2013-3-8 09:25 | 显示全部楼层
dirtwillfly 发表于 2013-3-7 11:44
在收到新数据时进行发送不行吗?这不就是实时吗

收到新数据是客户端发一个查询后才发送,我要的是客户端不发数据主动将串口收到的数据发送到客户端。
dirtwillfly 发表于 2013-3-9 09:17 | 显示全部楼层
BitFu 发表于 2013-3-8 09:25
收到新数据是客户端发一个查询后才发送,我要的是客户端不发数据主动将串口收到的数据发送到客户端。 ...

你用软件虚造一个查询信号,他不就主动发送了
jerkoh 发表于 2013-3-10 20:58 | 显示全部楼层
本帖最后由 jerkoh 于 2013-3-11 01:30 编辑

  楼主,用uIP1.0 做TCP/IP Server 转串口的话(双向/透明/无协议/无时间规则的转发)
  你可能会碰到3个问题:

1.就是你说的,主动发送数据: a.通过newdata或者rxmit  这时刚好串口有数据,你捎带串口数据上传,也就是PSH+ACK功能。
                            b,通过uip_poll() 这个默认是500ms一次,这样对于实时性和大量数据的串口接收要求发送出去的话是头痛的问题(丢数据概率也高 如果缓冲小的话)。
                              当然可以改periodic_timer,但改小了后,你会发现问题更多。
                            c,连续发送数据话,一进入uip_acked 模式就好处理了.实时性也较好 psh  ack  psh ack  psh ack........的处理
                              但TCP/IP转串口的话 往往很难有c的理想模式进入给你这么发。

2.非常关键的一点uIP的appcall 函数是针对当前的conn的操作,一旦你要实现server的 keepalive功能。你会发现只能开一个client socket才能实现稳定的keepalive功能
  如果多个client连接后 不进行通信了,虽然可以keepalive到某个client到死期了.但你没法使用appcall 函数去对其中的某一个进行abort.也就是关闭不了它,一直被它耗着。
  如果强行关闭会关了不该关掉的
  如果要实现主动断开某个client,那么uip.c 的process函数要大动刀子.
  不管客户端软件做的多好,如果server不实现keepalive功能的话,我认为总会某些情况出现uIP1.0一直不释放client,client永远无法连接server,最后只能重启uIP.
2013-03-11 01:25 注意上面的问题2:发完帖子,我又好好想了下, 这个问题完全可以不动uIP.c文件  我重新编写keepalive功能代码,测试发现已经彻底的解决了,                                                                 所以uIP协议栈是不存在我说的keepalive问题的:victory:

3.可以研究下uIP1.0的 psock.c,uip-split.c 也许可以有挖掘的地方。


//--------------TCP/IP 状态迁移标记----------------------------------------------------------------------------------------------------------------------------------------
unsigned char __IO  uip_poll_ack_static  =0;          //CLINET与SERVER的数据通信状态标记,上电默认值为0=客户端错误 断开或者被关闭了

#define   CLINT_ACKED_CLOSED             0              //服务器认为:客户端错误,断开或者被关闭了状态
#define   CLINT_ACKED_SYNACK             1              //服务器认为:客户端发起SYN后服务器回应SYN+ACK的无数据ACKED状态
#define   SERVER_ACTIVE_SEND             2               //服务器认为:客户端首次连接成功的状态下,并且client没发数据过来, 服务器主动向客户端发了数据后状态
#define   CLINT_NEWDAT_ACKED_CARRY       3            //服务器认为:客户端发送新数据给服务器后,服务器进入NEWDATA状态,服务器利用PSH+ACK模式将串口数据捎带发送到client
#define   CLINT_ACKED_CARRY              4           //服务器认为:客户端ACKED了EWDATA模式下稍带的服务器数据(CARRY模式的数据)
#define   CLINT_ACKED_NORMAL             5           //服务器认为:一直在服务器发数据->客户端ACKED->服务器发数据->客户端ACKED模式  正常循环模式,并未出现NEWDATA状态下的稍带
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------

我大概想了这么一个思路 通过上面的状态可以试试看。(但还是不适合那种一旦pc client连接上uip1.0 server后,client不发数据,而server的串口是时间随机主动要求转发给client,效率太差)

描述错误的地方请多指正、交流。

jerkoh 发表于 2013-3-10 21:18 | 显示全部楼层
dirtwillfly版主的方法: 用软件虚造一个查询信号,就主动发送了
这是个好的办法。
我也测试过。

但如果仔细追踪uIP1.0协议的运行机制话,你会发现client 如果连接上后,不与server进行数据交换通信,在回调的uip_appcall里面是
不允许你随意发一个len=0 的ACK 之类的查询信号,因为uip_appcall进入时 都是产生了flag的 包括poll,要对这些flag做正确操作。
随意发一个查询信号回到process函数 uIP也不会理睬的,除非对process函数改造。


kaly_liu 发表于 2013-5-2 15:49 | 显示全部楼层
jerkoh 发表于 2013-3-10 21:18
dirtwillfly版主的方法: 用软件虚造一个查询信号,就主动发送了
这是个好的办法。
我也测试过。

我在网上查了,说是UIP可以实现TCP服务器的主动发送的,只需要重组包什么的,有人这么弄的,但是不知道如何实现,我试了下,好像不行···不知道高手可否赐教。

  1. void SockTCP_Send(const void  *dat,u8_t len)                  //自己加的tcp主动发送函数。
  2. {                                            
  3.        u8_t c,i;
  4.         u32_t sember;
  5.         for(c = 0;c < UIP_CONNS;c ++)
  6.         {
  7.                 if(uip_conns[c].tcpstateflags == ESTABLISHED)               
  8.                 {                        
  9.                         BUF->ackno[0] = uip_conns[c].rcv_nxt[0];
  10.                            BUF->ackno[1] = uip_conns[c].rcv_nxt[1];
  11.                            BUF->ackno[2] = uip_conns[c].rcv_nxt[2];
  12.                            BUF->ackno[3] = uip_conns[c].rcv_nxt[3];
  13.                         
  14.                            BUF->seqno[0] = uip_conns[c].snd_nxt[0];
  15.                            BUF->seqno[1] = uip_conns[c].snd_nxt[1];
  16.                            BUF->seqno[2] = uip_conns[c].snd_nxt[2];
  17.                     BUF->seqno[3] = uip_conns[c].snd_nxt[3]; //低位
  18.                         sember = (uip_conns[c].snd_nxt[0] << 24) + (uip_conns[c].snd_nxt[1] << 16) +
  19.                                         (uip_conns[c].snd_nxt[2] <<8) + uip_conns[c].snd_nxt[3];
  20.                         sember += len;
  21.                         if(sember == 0xfffffff0)
  22.                                 sember = 0x001;
  23.                         for(i = 0;i < 4;i ++)
  24.                         {
  25.                                 uip_conns[c].snd_nxt[3-i] = (u8_t)(sember & 0x00ff);
  26.                                 sember = (sember >> 8);
  27.                         }

  28.                     BUF->proto = UIP_PROTO_TCP;
  29.                     BUF->srcport =  uip_conns[c].lport;
  30.                     BUF->destport = uip_conns[c].rport;         //端口

  31.                         BUF->flags = 0x18;
  32.                         BUF->tcpoffset = 0x50;

  33.   BUF->srcipaddr[0] = uip_hostaddr[0];
  34.   BUF->srcipaddr[1] = uip_hostaddr[1];
  35.   BUF->destipaddr[0] = uip_conn->ripaddr[0];
  36.   BUF->destipaddr[1] = uip_conn->ripaddr[1];


  37.                       BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8);
  38.                       BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff);
  39.                            BUF->ttl = UIP_TTL;
  40.                         uip_len = 40 + len;
  41.                         memcpy(uip_buf + 54,(dat),len);
  42.                            BUF->len[0] = (uip_len >> 8);
  43.                            BUF->len[1] = (uip_len & 0xff);
  44.                            BUF->urgp[0] = BUF->urgp[1] = 0;
  45.                     BUF->tcpchksum = 0;
  46.                     BUF->tcpchksum = ~(uip_tcpchksum());

  47.                        BUF->vhl = 0x45;         //我们一般用的都是ipv4协议
  48.                       BUF->tos = 0;
  49.                        BUF->ipoffset[0] = BUF->ipoffset[1] = 0;
  50.                     ++ipid;
  51.                     BUF->ipid[0] = ipid >> 8;
  52.                     BUF->ipid[1] = ipid & 0xff;
  53.                        BUF->ipchksum = 0;
  54.                        BUF->ipchksum = ~(uip_ipchksum());
  55.               
  56.                         uip_arp_out();
  57.                     network_device_send();

  58.                 }                                
  59.         }      
  60. }
jerkoh 发表于 2013-5-4 03:19 | 显示全部楼层
这个我看过,实际脱离了uip的uip_process  的callback

强制不关核心代码调度 标记 时间,自己组包发送。

不是很好的解决方法。
kaly_liu 发表于 2013-5-4 10:56 | 显示全部楼层
哦 好的 谢谢
kaly_liu 发表于 2013-6-6 10:37 | 显示全部楼层
jerkoh 发表于 2013-5-4 03:19
这个我看过,实际脱离了uip的uip_process  的callback

强制不关核心代码调度 标记 时间,自己组包发送。

高手,帮忙看看这个问题啊:https://bbs.21ic.com/icview-562956-1-1.html
kaly_liu 发表于 2013-6-8 16:33 | 显示全部楼层
jerkoh 发表于 2013-3-10 21:18
dirtwillfly版主的方法: 用软件虚造一个查询信号,就主动发送了
这是个好的办法。
我也测试过。

您好,不知道您研究uip多久了,想请教下一个问题:在uip中的那个 以太网帧 校验代码在那个文件里?我就找到了IP TCP校验和计算的代码,在uip_arch.c文件里,里面还有一个函数:void uip_add32(u8_t *op32, u16_t op16) 不知道这个函数是用来干嘛的额···求指点啊~~~
andrewpei 发表于 2013-8-11 17:17 | 显示全部楼层
这个讨论贴有点意思。留印一下
tcpln2009 发表于 2014-12-13 15:46 | 显示全部楼层
额,我也遇到这个问题了,现在还在着急解决中。。。
chai1836 发表于 2015-3-25 10:47 | 显示全部楼层
jerkoh 发表于 2013-3-10 20:58
楼主,用uIP1.0 做TCP/IP Server 转串口的话(双向/透明/无协议/无时间规则的转发)
  你可能会碰到3个问 ...

小弟最近正在研究用stm32和dm9000a做透明串口,可以发一份吗,非常感谢
jf7686 发表于 2015-10-23 16:00 | 显示全部楼层
請問大大如何實現 uip keep alive 可以分享一下嘛?謝謝
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:芯艺工作室

195

主题

1058

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部