LInux Socket绑定网卡和IP

#include <errno.h> // errno
#include <sys/socket.h> // socket
#include <string.h> // strerror
#include <unistd.h> // close

#define LOG_TAG "[exam1_socket_bind]"

static void sock_create_bind(void);
static int32_t socket_set_eth_interface_and_ip_addr(const char *eth_interface, const char *ip_addr);

// 通过ifconfig查看网口、ip;(ens33: inet 192.168.54.231)
void exam1_socket_bind_test(void)
{
VOID_FUNC_ENTER();
// eth interface or ip addr, can set NULL.
socket_set_eth_interface_and_ip_addr("ens33", "192.168.54.231");
sock_create_bind();
VOID_FUNC_EXIT();
}

// ip addr
#include <netinet/in.h>
static uint8_t g_socket_ip_flag = 0;
struct sockaddr_in g_socket_serv_addr;
// eth interface
#include <net/if.h> // ifreq
#include <arpa/inet.h> // inet_addr
#define SOCKET_IFNAME_MAX_LEN (16)
static uint8_t g_socket_ifname_flag = 0;
static char g_socket_ifname[SOCKET_IFNAME_MAX_LEN] = { 0 };
static uint8_t g_socket_ifname_len = 0;

static int32_t socket_set_eth_interface_and_ip_addr(const char *eth_interface, const char *ip_addr)
{
int32_t ret = 0;
do {

if (eth_interface != NULL) {
LOGD("socket ifname=%s, len=%d", eth_interface, (int32_t)strlen(eth_interface));
memset(g_socket_ifname, 0, SOCKET_IFNAME_MAX_LEN);
memmove((char *)g_socket_ifname, eth_interface, strlen(eth_interface)+1);
g_socket_ifname_len = strlen(eth_interface)+1;
g_socket_ifname_flag = 1;
}

if (ip_addr != NULL) {
LOGD("socket ip_addr=%s, len=%d", ip_addr, (int32_t)strlen(ip_addr));
memset(&g_socket_serv_addr, 0, sizeof(g_socket_serv_addr));
g_socket_serv_addr.sin_family = AF_INET;
/* INADDR_ANY表示不管是哪个网卡接收到数据,只要目的端口是SERV_PORT,就会被该应用程序接收到 */
//g_socket_serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
g_socket_serv_addr.sin_addr.s_addr = inet_addr(ip_addr);
// g_socket_serv_addr.sin_port = htons(8080);
g_socket_serv_addr.sin_port = 0;
g_socket_ip_flag = 1;
}

} while (0);

return ret;
}


/*
* Create a socket handler.
*
* @return:
* >= 0: succeeds, identifier of the socket handler;
* -1: failed;
*/
static void sock_create_bind(void)
{
int32_t sock = 0;

do {
// sock = socket(AF_INET, SOCK_STREAM, 0);
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
LOGE("socket fail, errno=%s", strerror(errno));
break;
} else {
LOGI("socket create success, sock=%d", sock);
}

LOGD("socket=%d, ifname flag=%d", sock, g_socket_ifname_flag);
if (g_socket_ifname_flag == 1) {
LOGD("socket ifname=%s", g_socket_ifname);
struct ifreq interface;
strncpy(interface.ifr_ifrn.ifrn_name, g_socket_ifname, g_socket_ifname_len);
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, (char *)&interface, sizeof(interface)) < 0) {
LOGE("setsockopt failed, errno=%s", strerror(errno));
} else {
LOGD("setsockopt(%s) success", g_socket_ifname);
}
}

LOGD("socket=%d, ip flag=%d", sock, g_socket_ip_flag);
if (g_socket_ip_flag == 1) {
if (bind(sock, (struct sockaddr *)&g_socket_serv_addr, sizeof(g_socket_serv_addr)) == -1) {
LOGE("bind ip failed, errno=%s", strerror(errno));
} else {
LOGD("bind ip success");
}
}
} while (0);

// only test, close sock
if (sock > 0) {
LOGI("only test, close sock(%d)", sock);
(void)close(sock);
sock = -1;
}
}

/*
参考资料:

socket 绑定网口
Linux 套接字编程 套接字选项SO_BINDTODEVICE 绑定接口 示例
https://blog.csdn.net/fuyuande/article/details/82728734
linux下socket指定网卡
https://blog.csdn.net/weixin_42525261/article/details/116681809
Linux的SOCKET编程详解:
https://www.cnblogs.com/zhaobin-diray/p/9073298.html
socket 绑定ip
linux之socket相关的函数结构体解析
https://blog.csdn.net/weixin_37921201/article/details/90107919
Socket Server指定监听端口和IP
https://blog.csdn.net/qq_34039018/article/details/101026332
socket 通信关于bind IP地址
https://blog.csdn.net/beilingshan/article/details/72821076

Linux多播问题(No such device)解决方法
https://zhuanlan.zhihu.com/p/291203312

原文地址:https://www.cnblogs.com/zwh0214/p/15348546.html