最近正在进行一个Zynq项目,根据设计需求,需要将上位机作为UDP服务器,而FPGA则充当UDP客户端。同时,服务器需要能够接收和控制多个UDP客户端。
开发过程中,我是基于lwip UDP Perf Client 官方模版开发的。我遇到了以下几个问题及注意事项,做一个记录:
1、每个客户端使用同一个IP地址的不同的源端口号,还是选择使用不同的IP地址来实现多个UDP客户端的接收和控制。
(1)如果使用同一个IP地址的不同的源端口号,则需要网络初始化udp_bind()时,在port = udp_new_port()函数中,给每个客户端设置不同的源端口号(0~65535),Xilinx UDP例程默认(49152)。
(2)使用不同的IP地址。这个简单,直接在如下代码定义全局变量local_ip_addr的值。
assign_default_ip(&(netif->ip_addr), &(netif->netmask), &(netif->gw));
2、由于多个客户端,有的客户端启动慢,或者启动时网线连接异常,等待一会,串口会显示“Waiting for PHY to complete autonegotiation”——“Auto negotiation error”错误。这个错误叫自协商错误,通常发生在网络设备启动时候,进行自动协商时,表示设备无法成功协商和达成通信参数。查阅资料,主要原因可能是兼容性问题、电缆问题、配置错误和硬件问题。
本工程,是由于硬件网线连接问题,所以,如果在启动时候,未连接成功,设计成等待即可。
通过debug定位,是在初始化网络过程中,againxemacpsif_physpeed.c文件中,get_Marvell_phy_speed()函数,如果等待约30s未正确连接,则跳出等待,初始化失败。故,只要在这里一直等待硬件连接即可。
3、多台网络设备连接一个服务器,记得每一台设备的MAC地址要不一样,否则会通信异常,或者设备连接时而连接时而断线。(容易马虎忘记)
4、外场设备组网,连接外网,接入政务云时,无法连接。原因:目标端口号是8080,查阅资料可知,:8080端口以及80端口属于高危端口,一般不私用,是被用于WWW代理服务的。
常见的高危端口有:0、21、22、23、25、80、102、110、111、119、135、137、138、139、161、177、389、1900-1905、5353、5355、5357、5432、6666-6669、8080、11211等,以及
1-1023:称为"保留端口"或"系统端口",它们用于常见的服务和协议,如HTTP(端口80)、FTP(端口21)和SSH(端口22)。通常,这些端口需要管理员权限才能使用。
不建议私用。
UDP客户端代码:
static void print_udp_conn_stats(void)
{
xil_printf("local %s port %d connected with ",
inet_ntoa(server_netif.ip_addr),
pcb->local_port);
xil_printf("%s port %d\r\n",inet_ntoa(pcb->remote_ip),
pcb->remote_port);
}
static void recv_callback(void *arg, struct udp_pcb *tpcb, struct pbuf *p, ip_addr_t *ip, u16_t port)
{
/* do not read the packet if we are not in ESTABLISHED state */
if (!p)
{
udp_remove(tpcb);
udp_recv(pcb,NULL,NULL);
return ;
}
g_udp_recv_flag = 1;
/* indicate that the packet has been received */
ReceiveDataAnalysis(tpcb,p);
/* free the received pbuf */
pbuf_free(p);
return ;
}
/* Create Client PCB */
void start_application(void)
{
err_t err;
ip_addr_t remote_addr;
int port = g_Net_Port[1]<<8 | g_Net_Port[0];
char str_server_ip_addr[16] = {0};
sprintf(str_server_ip_addr, "%d.%d.%d.%d",
server_ip_addr.ip0, server_ip_addr.ip1, server_ip_addr.ip2, server_ip_addr.ip3);
err = inet_aton(str_server_ip_addr, &remote_addr);
if (!err) {
xil_printf("Invalid Server IP address: %d\r\n", err);
return;
}
/* Create Client PCB */
pcb = udp_new();
if (!pcb) {
xil_printf("Error in PCB creation. out of memory\r\n");
return;
}
err = udp_connect(pcb, &remote_addr, port);
if (err != ERR_OK)
{
xil_printf("udp_client: Error on udp_connect: %d\r\n", err);
udp_remove(pcb);
return;
}
else
{
udp_recv(pcb,(udp_recv_fn)recv_callback,NULL);
g_user_pcb = pcb;
}
/* Wait for successful connection */
usleep(10);
print_udp_conn_stats();
}
REF:
80 8080 端口不能用_80端口和8080不能用_wandersky0822的博客-CSDN博客