socket---纯C

总代码:

复制代码
    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: 端口,但此处暂时不考虑。

相关推荐
Nebula_g2 天前
Java实现本地Socket通信(二)
java·开发语言·socket·线程·chat
Nebula_g5 天前
Java实现本地Socket通信(三)
java·开发语言·学习·socket·可视化
ShineWinsu11 天前
对于Linux:模版方法类的解析以及socket、TcpSocket的封装
linux·c++·面试·socket·模板方法模式·封装·tcpsocket
CodeStats21 天前
【Linux IO】从文件描述符到硬件中断:Linux IO 系统底层完全拆解
java·linux·开发语言·io·socket
十五年专注C++开发23 天前
fatal error C1189: #error: WinSock.h has already been included 的解决方案
c++·socket·boost
东南门吹雪2 个月前
JAVA TCP socket编程框架
java·高并发·socket·tcp·nio
阿钱真强道2 个月前
29 鸿蒙LiteOS RK2206 Socket编程实战 UDP通信+LWIP原理全解析
udp·socket·鸿蒙·liteos·开源鸿蒙·瑞芯微·rk2206
金融支付架构实战指南2 个月前
Java Socket 全网read/write底层原理 + 避坑实战
socket·tcp·write·listen·connect
知无不研2 个月前
对套接字的深入理解
linux·服务器·网络·c++·socket·网络套接字