总代码:
int m_sendSocket; // 发送套接字
// 以下为发送套接字创建
// 创建UDP方式的发送套接字
if ((m_sendSocket = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
printf("UdpFuc::Create Send Socket ERROR!\n");
return 0;
}
char *target_addr = "192.9.2.27";
int target_port = 6000;
char* send_buf = new char[15];
strcpy(send_buf,"12345");
int length = 15;
struct sockaddr_in dstAddr;
int sockAddrSize;
sockAddrSize = sizeof (struct sockaddr_in);
memset ((char *) &dstAddr, '\0', sockAddrSize);
// dstAddr.sin_len = sockAddrSize;
dstAddr.sin_family = AF_INET;
dstAddr.sin_port = htons(target_port);
dstAddr.sin_addr.s_addr = inet_addr(target_addr);
int ret = sendto(m_sendSocket, (const char *)send_buf, length, 0, (struct sockaddr *)&dstAddr, sockAddrSize);
if(ret == -1)
{
perror("sendto error");
}
分块代码1:
cpp
int m_sendSocket; // 发送套接字
// 以下为发送套接字创建
// 创建UDP方式的发送套接字
if ((m_sendSocket = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
printf("UdpFuc::Create Send Socket ERROR!\n");
return 0;
}
创建一个 UDP 协议的发送端套接字文件描述符 ,用于后续通过**
sendto()** 向指定 IP 端口发送 UDP 数据包,创建失败直接打印错误并返回。
socket()函数返回值是整型文件描述符(fd) ,Linux/Windows(Winsock)均用 int接收;参数 1:
AF_INET地址族,代表 IPv4 网络协议 ; 可选:
AF_INET6为 IPv6,这里是普通 IPv4 UDP。参数 2:
SOCK_DGRAM套接字类型 = 数据报套接字 ,固定对应 UDP 无连接协议 ; 对比:
SOCK_STREAM是 TCP 流式套接字。第三个参数指定具体使用的传输层协议号 ; 当前场景:
AF_INET + SOCK_DGRAM,填0= 让系统自动选择默认协议,等价于手动写IPPROTO_UDP。int socket(int domain, int type, int protocol);
domain=AF_INET(IPv4)
① type = SOCK_STREAM(TCP 流式)
- protocol = 0 → 默认:IPPROTO_TCP(TCP) 只能填 TCP,填别的不合法。
② type = SOCK_DGRAM(数据报)
- protocol = 0 → 默认:IPPROTO_UDP (UDP) 也就是你代码里的情况,
0自动选 UDP。
上面的代码可以向192.9.2.27的6000端口发送一段报文。
我的电脑有很多网卡,我使用了其中两个网卡:
192.9.2.100
192.9.10.2
这时候我的socket的ip是使用192.9.10.2,我其实想要使用192.9.2.100。
UDP socket 默认不绑定本地网卡 IP,操作系统路由表自动选出口网卡,所以发包走了 192.9.10.2。
解决办法:给发送 socket 强制 bind 绑定到指定网卡 IP:192.9.2.100 ,后续所有sendto 都会从这块网卡发出。
使用这段代码来绑定(bind)特定网卡(特定IP):
cpp
localAddr.sin_family = AF_INET;
localAddr.sin_addr.s_addr = inet_addr("192.9.2.100"); // 指定网卡IP
localAddr.sin_port = htons(0); // 端口填0:系统自动随机分配本地端口
// 执行bind绑定
if (bind(m_sendSocket, (struct sockaddr *)&localAddr, sizeof(localAddr)) == -1)
{
perror("bind 192.9.2.100 failed");
close(m_sendSocket);
return 0;
}
默认情况下:同一个 IP + 同一个端口,UDP 不允许两个 socket 同时 bind,第二个 bind 直接报错(Address already in use)
1.不加任何特殊选项
cpp
bind(sock1, addr, len); // 绑定 192.168.1.20:8888
bind(sock2, addr, len); // 直接失败,EADDRINUSE
协议 (UDP) + 本地 IP + 本地端口 全局唯一,只能被一个套接字占用。
也可以通过一些办法来实现多UDP socket 绑定同一 IP: 端口,但此处暂时不考虑。