原因
下面流程导致创建多网卡 socket 无法指定网卡
在 sal_socket 时,在 socket_init 中绑定了网卡为 default,然后通过 网卡下面的 protocol family socket 创建网卡 pf->skt_ops->socket(domain, type, protocol)
int sal_socket(int domain, int type, int protocol)
{
int retval;
int socket, proto_socket;
struct sal_socket *sock;
struct sal_proto_family *pf;
/* allocate a new socket and registered socket options */
socket = socket_new();
if (socket < 0)
{
return -1;
}
/* get sal socket object by socket descriptor */
sock = sal_get_socket(socket);
if (sock == RT_NULL)
{
socket_delete(socket);
return -1;
}
/* Initialize sal socket object */
retval = socket_init(domain, type, protocol, &sock);
if (retval < 0)
{
LOG_E("SAL socket protocol family input failed, return error %d.", retval);
socket_delete(socket);
return -1;
}
/* valid the network interface socket opreation */
SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, socket);
proto_socket = pf->skt_ops->socket(domain, type, protocol);
if (proto_socket >= 0)
{
#ifdef SAL_USING_TLS
if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, socket))
{
sock->user_data_tls = proto_tls->ops->socket(socket);
if (sock->user_data_tls == RT_NULL)
{
socket_delete(socket);
return -1;
}
}
#endif
sock->user_data = (void *) proto_socket;
return sock->socket;
}
socket_delete(socket);
return -1;
}
创建不同协议类型的socket引用关系
解决办法 解决方案要基于前篇文章2021/07/14 LwIP 2.0.2 多网卡 ping;LwIP 指定网卡ping 在创建 socket 的过程中,通过 sin_family 指定使用 AF_WIZ, AF_AT, AF_INET(lwip), 然后通过 bind 函数,二次选择网卡; socket(AF_INET, SOCK_STREAM, 0) wiznet family = AF_WIZ sec_family = AF_INET lwip family=AF_INET sec_family = AF_UNSPEC at device family=AF_AT sec_family = AF_INET 修改过程 修改函数 socket_init rt-threadcomponents
etsal_socketsrcsal_socket.c 修改函数,通过 sin_family 指定使用 AF_WIZ, AF_AT, AF_INET(lwip); static int socket_init(int family, int type, int protocol, struct sal_socket **res) // 420 行 /** * This function will initialize sal socket object and set socket options * * @param family protocol family * @param type socket type * @param protocol transfer Protocol * @param res sal socket object address * * @Return 0 : socket initialize success * -1 : input the wrong family * -2 : input the wrong socket type * -3 : get network interface failed */ static int socket_init(int family, int type, int protocol, struct sal_socket **res) { struct sal_socket *sock; struct sal_proto_family *pf; struct netdev *netdv_def = netdev_default; struct netdev *netdev = RT_NULL; rt_bool_t flag = RT_FALSE; if (family < 0 || family > AF_MAX) { return -1; } if (type < 0 || type > SOCK_MAX) { return -2; } sock = *res; sock->domain = family; sock->type = type; sock->protocol = protocol; netdv_def = netdev_get_by_family(family); if (netdv_def == RT_NULL) { netdv_def = netdev_default; } if (netdv_def && netdev_is_up(netdv_def)) { /* check default network interface device protocol family */ pf = (struct sal_proto_family *) netdv_def->sal_user_data; if (pf != RT_NULL && pf->skt_ops && (pf->family == family || pf->sec_family == family)) { sock->netdev = netdv_def; flag = RT_TRUE; } } if (flag == RT_FALSE) { /* get network interface device by protocol family */ netdev = netdev_get_by_family(family); if (netdev == RT_NULL) { LOG_E("not find network interface device by protocol family(%d).", family); return -3; } sock->netdev = netdev; } LOG_I("use network interface: %s", sock->netdev->name); return 0; } 测试多网卡功能 #include #include /* 使用BSD socket,需要包含socket.h头文件 */ #include #include #include #include #define LOG_TAG "test_multi_netif" #define LOG_LVL LOG_LVL_DBG #define BUFSZ 256 #define SEND_DATASZ 256 #define SAY_BUFSZ 240 #define THREAD_PRIORITY 20 #define THREAD_STACK_SIZE 2048 #define THREAD_TIMESLICE 5 #define EVENT_CLOSE_SOCK 0x01 #define SERVER_E0 "139.155.51.105" #define SERVER_W0 "172.18.44.66" static int close_socket(int *sock); static char send_data[80] = {0}; /* 发送用到的数据 */ typedef struct TEST_MULTI_NETIF { char netdev_name[8]; int sock; int netdev_type; rt_event_t event; }TCP_CLIENT; TCP_CLIENT tcp_e0; TCP_CLIENT tcp_w0; static int socket_connect(const char *dest, struct netdev *dev) { struct hostent *host; struct sockaddr_in server_addr; int sock = -1; int port = 9008; struct sockaddr_in local; /* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */ host = gethostbyname(dest); /* 创建一个socket,类型是SOCKET_STREAM,TCP类型 */ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { /* 创建socket失败 */ log_e("create socket error"); /* 释放接收缓冲 */ /* rt_free(recv_data); */ return -1; } log_i("create success"); /* 初始化预连接的服务端地址 */ server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); server_addr.sin_addr = *((struct in_addr *)host->h_addr); rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero)); local.sin_len = sizeof(local); local.sin_family = AF_INET; local.sin_port = 0; local.sin_addr.s_addr = dev->ip_addr.addr; if (dev->ip_addr.addr != 0) { bind(sock, (struct sockaddr *)&local, sizeof(struct sockaddr_in)); } log_i("bind %x success", local.sin_addr.s_addr); /* 连接到服务端 */ if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) != RT_EOK) { /* 连接失败 */ log_e("Connect server [%s] failed!
", dest); closesocket(sock); return -1; } log_i("connect server success"); return sock; } static int close_socket(int *sock) { if (*sock > 0) { log_d("disconnect server!
"); closesocket(*sock); *sock = -1; } } /* create receive thread */ static void thread_rece_entry(void* parameter) { char *recv_data; int bytes_received; TCP_CLIENT *client = (TCP_CLIENT *)parameter; /* int no = (int) parameter; #<{(| 获得线程的入口参数 |)}># */ /* 分配用于存放接收数据的缓冲 */ recv_data = rt_malloc(BUFSZ); if (recv_data == RT_NULL) { rt_kprintf("No memory
"); } while(1) { /* 从sock连接中接收最大BUFSZ - 1字节数据 */ bytes_received = recv(client->sock, recv_data, BUFSZ - 1, 0); if (bytes_received < 0) { /* 接收失败,关闭这个连接 */ log_d("received less than zero, close the socket."); rt_free(recv_data); rt_event_send(client->event, EVENT_CLOSE_SOCK); return; } else if (bytes_received == 0) { /* 默认 recv 为阻塞模式,此时收到0认为连接出错,关闭这个连接 */ log_d("received equal zero, close the socket."); rt_free(recv_data); rt_event_send(client->event, EVENT_CLOSE_SOCK); return; } recv_data[bytes_received] = ' |