完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
在只有一个物理网卡的情况下,可以通过软件虚拟多个 IP地址 ,分时通讯。
协议栈: LwIP 主芯片:STM32F107VC 实现 首先移植 LwIP ,保证单个 IP地址 时可用。 然后添加虚拟网卡: void LwIP_Init(void) { /* 添加网卡1 */ IP4_ADDR( ipaddr1, 192, 168, 0, 234); IP4_ADDR( netmask1, 255, 255, 255, 0); IP4_ADDR( gw1, 192, 168, 0, 1); netif_add( netif1, ipaddr1, netmask1, gw1, NULL, ethernetif_init, ethernet_input); netif_set_up( netif1); netif_set_default( netif1); /* 添加网卡2 */ IP4_ADDR( ipaddr2, 192, 168, 1, 234); IP4_ADDR( netmask2, 255, 255, 255, 0); IP4_ADDR( gw2, 192, 168, 1, 1); netif_add( netif2, ipaddr2, netmask2, gw2, NULL, ethernetif_init, ethernet_input); netif_set_up( netif2); /* 新建UDP通信 */ struct udp_pcb *UdpPcb; /* Create a new UDP control block */ UdpPcb = udp_new(); /* Bind the upcb to any IP address and the UDP_PORT port*/ udp_bind(UdpPcb, IP_ADDR_ANY, UDP_CLIENT_PORT); /* Set a receive callback for the upcb */ udp_recv(UdpPcb, udp_client_callback, NULL); } 这样处理之后,出现下面的问题: 有些数据包会在网卡中逗留,在不确定的时间后,发出去 数据包每次都发了两次 第一张网卡的 IP地址 收不到数据,甚至于使用以太网调试助手向该 IP 发送数据都抓不到数据包。 根据以太网通信协议,局域网内数据收发,需要使用 MAC 地址通讯,因此首先需要发送 ARP 数据包,需要向目的 IP地址 发送协议包,请求对方的 MAC地址 。通过抓包工具查看,果然是这样,电脑端发送的 ARP 数据包,设备没有回复。 因此修改 ARP层 。 /* ********************************************************************************************************* * Function Name : GetActiveNetif * Description : 获取当前活动的网卡 * Input : None * Output : None * Return : None ********************************************************************************************************* */ struct netif *GetActiveNetif(struct ip_addr *src_ip) { struct netif *curNetif = NULL; if (ip_addr_cmp(src_ip, netif1.ip_addr)) { curNetif = netif1; } else if (ip_addr_cmp(src_ip, netif2.ip_addr)) { curNetif = netif2; } return curNetif; } 通过解析数据包中的 源IP 字段,和当前 2 张网卡中的 源IP 字段进行比较,从而找到数据包是发送给哪一张网卡的。 void etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) { /* this interface is not configured? */ if (netif->ip_addr.addr == 0) { for_us = 0; } else { /* ARP packet directed to us? */ struct netif *GetActiveNetif(struct ip_addr *src_ip); struct netif *activeNetif = GetActiveNetif( dipaddr); if (activeNetif != NULL) { for_us = 1; netif = activeNetif; } } /* ARP message directed to us? */ if (for_us) { /* add IP address in ARP cache; assume requester wants to talk to us. * can result in directly sending the queued packets for this host. */ update_arp_entry(netif, sipaddr, (hdr->shwaddr), ETHARP_TRY_HARD); /* ARP message not directed to us? */ } else { /* update the source IP address in the cache, if present */ update_arp_entry(netif, sipaddr, (hdr->shwaddr), 0); } } 通过上述修改,上位机的数据包就可以收到了。 /** * In this function, the hardware should be initialized. * Called from ethernetif_init(). * * @param netif the already initialized lwip network interface structure * for this ethernetif */ static void low_level_init(struct netif *netif) { /* device capabilities */ /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_LINK_UP; } 根据上面提示,如果有多个网络,需要去掉 NETIF_FLAG_ETHARP 字段。 OK ,经过上述修改,两个 IP地址 都可以收到数据包。 总结 IP地址 需要配置为不同网段 参考 IP 路由规则: /** * Finds the appropriate network interface for a given IP address. It * searches the list of network interfaces linearly. A match is found * if the masked IP address of the network interface equals the masked * IP address given to the function. * * @param dest the destination IP address for which to find the route * @return the netif on which to send to reach dest */ struct netif * ip_route(struct ip_addr *dest) { struct netif *netif; /* iterate through netifs */ for(netif = netif_list; netif != NULL; netif = netif->next) { /* network mask matches? */ if (netif_is_up(netif)) { if (ip_addr_netcmp(dest, (netif->ip_addr), (netif->netmask))) { /* return netif on which to forward IP packet */ return netif; } } } if ((netif_default == NULL) || (!netif_is_up(netif_default))) { LWIP_DEBUGF(IP_DEBUG | 2, ("ip_route: No route to 0x%"X32_F"n", dest->addr)); IP_STATS_INC(ip.rterr); snmp_inc_ipoutnoroutes(); return NULL; } /* no matching netif found, use default netif */ return netif_default; } 如果两张网卡的 IP地址 在同一个网段,那么在遍历网卡时,会优先找到最后添加的网卡,也就是说,不管你往哪个网卡发送数据包,在设备回复数据时,都会从第二张网卡回复数据。 比如说:向 IP (192, 168, 0, 234) 发送数据包,收到数据回复时,源 IP地址 会变成 IP(192, 168, 1, 234) 。 如果想要两张网卡独立工作,都可以正常收发数据,需要将两张网卡的 IP地址 设置为不同的网段,同时电脑端需要和设备端设置在同一个网段! 比如: 主机1: IP: 192.168.0.88 MASK: 255.255.255.0 GATEWAY:192.168.0.1 设备1: IP: 192.168.0.249 MASK: 255.255.255.0 GATEWAY:192.168.0.1 这样,主机1 和 设备1 可以正常通讯。 主机2: IP: 192.168.1.88 MASK: 255.255.255.0 GATEWAY:192.168.1.1 设备2: IP: 192.168.1.249 MASK: 255.255.255.0 GATEWAY:192.168.1.1 这样,主机2 和 设备2 可以正常通讯。 如果交叉会怎么样呢?你会发现抓包工具会显示目标不可达,因为他们不再同一个子网内! 如果设备1和设备2在同一个子网内会怎么样呢? 主机: IP: 192.168.0.88 MASK: 255.255.255.0 GATEWAY:192.168.0.1 设备1: IP: 192.168.0.249 MASK: 255.255.255.0 GATEWAY:192.168.0.1 设备2: IP: 192.168.0.248 MASK: 255.255.255.0 GATEWAY:192.168.0.1 现象: 主机 –> 设备1:设备2 –> 主机 主机 –> 设备2:设备2 –>主机 因此,我们得出结论: 只有在同一个子网内的主机和设备才可以正常收发数据 如果两台设备在同一个子网内,主机只能和最后添加的网卡绑定的 IP地址 正常通讯。和最开始添加的网卡通讯时,由于 ip_rout 的关系,将使用最后绑定网卡的 IP地址 回复! |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1627 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1550 浏览 1 评论
984 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
688 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1601 浏览 2 评论
1867浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
650浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
518浏览 3评论
536浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
506浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-24 15:11 , Processed in 0.850009 second(s), Total 79, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号