官方的以太网uip的demo是一个webserver,我将webserver等内容去掉,准备弄过网络与串口互转的设备,先贴一下代码,再说明问题:
uipMain.c中的uipMain函数
void uIPMain(void)
{
u8_t i, arptimer;
uip_eth_hdr *BUF = (uip_eth_hdr*)uip_buf;//uip_buf是一个1502大小的数组,用于全局来处理以太网帧
u32 size;
/* Initialize the uIP TCP/IP stack. */
uip_init();
arptimer = 0;
tcp_server_init();//此处将httpd_init改成了我的一个初始化函数
while(1)
{
/* Let the tapdev network device driver read an entire IP packet
into the uip_buf. If it must wait for more than 0.5 seconds, it
will return with the return value 0. If so, we know that it is
time to call upon the uip_periodic(). Otherwise, the tapdev has
received an IP packet that is to be processed by uIP. */
size = ETH_HandleRxPkt(uip_buf);//处理接收的包
if (size > 0)
uip_len = size;
if(uip_len <= 0x0)//表明读取数据超时
{
for(i = 0; i < UIP_CONNS; i++)//tcp部分
{
uip_periodic(i);
/* If the above function invocation resulted in data that
should be sent out on the network, the global variable
uip_len is set to a value > 0. */
if(uip_len > 0)
{
uip_arp_out();
TransmitPacket();
}
}/* end for */
#if UIP_UDP
for(i = 0; i < UIP_UDP_CONNS; i++)//udp部分
{
uip_udp_periodic(i);
/* If the above function invocation resulted in data that
should be sent out on the network, the global variable
uip_len is set to a value > 0. */
if(uip_len > 0)
{
uip_arp_out();
TransmitPacket();
}
} /* end for */
#endif /* UIP_UDP */
/* Call the ARP timer function every 10 seconds. */
if(++arptimer == 20)
{
uip_arp_timer();
arptimer = 0;
}
} /* end if(uip_len <= 0x0) */
else
{
if(BUF->type == htons(UIP_ETHTYPE_IP))//如果是IP包
{
uip_arp_ipin();
uip_input();
/* If the above function invocation resulted in data that
should be sent out on the network, the global variable
uip_len is set to a value > 0. */
if(uip_len > 0)
{
uip_arp_out();
TransmitPacket();
}
}
else if(BUF->type == htons(UIP_ETHTYPE_ARP))//如果是ARP包
{
uip_arp_arpin();
/* If the above function invocation resulted in data that
should be sent out on the network, the global variable
uip_len is set to a value > 0. */
if(uip_len > 0)
{
TransmitPacket();
}
}
} /* end else */
}
}
tcp_server.c
#include "uip.h"
#include "tcp_server.h"
#include <stdio.h>
#define HOST_IDLE 0 //主机空闲,一直处于监听状态
#define CLIENT_GET 1 //客户端连接上
#define DATA_SEND 2
struct tcp_server_state *tss;//tcp sever state
void tcp_server_init(void)
{
uip_listen(HTONS(1000));
}
/* 注意uip如果做为tcp服务器端向客户端发送数据只有三种方法
1.在收到新数据时进行发送
2.在需要重发时进行发送
3.在收到对方收到数据的ack确认后,如果有数据可以进行发送 */
void tcp_server_appcall(void)
{
tss = (struct tcp_server_state *)(uip_conn->appstate);
if(uip_connected()) //客户端接入
{
printf("Tcp Clinet In \r\n");
tss->state = CLIENT_GET;
return;
}
if(uip_newdata()|| uip_rexmit()) //收到新的数据
{
switch(tss->state)
{
case CLIENT_GET:
printf("Get The Clinet Data Num is %d\r\n",uip_datalen());
if(!uip_poll())
{
uip_send("ok\n", 3);
tss->state = DATA_SEND;
}
break;
default:break;
}
}
if(uip_acked() && tss->state == DATA_SEND)
{
tss->state = CLIENT_GET;
printf("send has been ack\r\n");
}
if(uip_poll())
{
//复制数据到缓冲区
return ;
}
if(uip_timedout())
{
printf("uip time out \r\n");
}
if(uip_aborted()) //是否客户端中断关闭
{
printf("The Client Is Aborted\r\n");
tss->state = HOST_IDLE;
}
if(uip_closed()) //是否客户端中断关闭
{
printf("The Client Is Closed\r\n");
tss->state = HOST_IDLE;
}
}
tcp_server.h
#ifndef _SERVER_H
#define _SERVER_H
#include "uipopt.h"
void tcp_server_init(void);
void tcp_server_appcall(void);
#ifndef UIP_APPCALL
#define UIP_APPCALL tcp_server_appcall
#endif
struct tcp_server_state {
u8_t state;
};
/* UIP_APPSTATE_SIZE: The size of the application-specific state
stored in the uip_conn structure. */
#ifndef UIP_APPSTATE_SIZE
#define UIP_APPSTATE_SIZE (sizeof(struct tcp_server_state))
#endif
#endif
现在问题是,我服务器端进行连接后,在第三次握手时,始终检测不到客户端的 ack包,而一直在发送syn ack包(二次握手用的包)?wrieshark抓图如下:
其中服务器端uip的ip设置为 192.168.0.102,客户端我的pc机 的ip设置为 192.168.1.101,是不是stm移植的uip有bug?请各位指导一下 |