你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

stm32 lwip怎样做到一个ip地址多个端口

[复制链接]
1597685605 提问时间:2018-8-22 11:51 /
有没有用stm32做过lwip一个IP地址多个端口通信的,亲大佬指点下
收藏 评论9 发布时间:2018-8-22 11:51

举报

9个回答
feixiang20 回答时间:2018-8-22 23:59:29
给你参考一个普及:

概述
在只有一个物理网卡的情况下,可以通过软件虚拟多个 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地址 回复!

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3 内容有点多啊

查看全部评分

wenyangzeng 回答时间:2018-8-22 13:20:08
lwip一个IP地址只能提供一路LWIP通讯吧?多个端口通讯要选择不同的硬件通讯端口和相应的通讯协议。

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

freeelectron 回答时间:2018-8-22 14:18:33
我记得lwip是支持多路socket的,试试建立多路socket,ip设置成一样的,port设置成不同的

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

1597685605 回答时间:2018-8-22 14:47:14
freeelectron 发表于 2018-8-22 14:18
我记得lwip是支持多路socket的,试试建立多路socket,ip设置成一样的,port设置成不同的 ...

哦哦哦,谢谢啊!
wudianjun2001 回答时间:2018-8-22 15:39:20
使用不同的端口,

评分

参与人数 1蝴蝶豆 +1 收起 理由
zero99 + 1

查看全部评分

1597685605 回答时间:2018-8-22 16:35:06

是的
1597685605 回答时间:2018-8-22 16:35:27
wenyangzeng 发表于 2018-8-22 13:20
lwip一个IP地址只能提供一路LWIP通讯吧?多个端口通讯要选择不同的硬件通讯端口和相应的通讯协议。 ...

就一个网口
1597685605 回答时间:2018-9-3 11:54:42
feixiang20 发表于 2018-8-22 23:59
给你参考一个普及:

概述

感谢大佬
单片机小小小小菜鸟 回答时间:2019-5-20 10:47:53
freeelectron 发表于 2018-8-22 14:18
我记得lwip是支持多路socket的,试试建立多路socket,ip设置成一样的,port设置成不同的 ...

为什么需要port不同?为什么网络调试助手可以开相同ip  port接收多个ip发过来的数据包?是因为LWIP协议栈和网路调试助手的协议栈不同吗?  我是新手  刚开始了解网口通讯相关东西,请大佬多指教啊

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版