UDP网络编程实战用法

该文章对萌新非常友善,值得一看

        其实网上使用 htonl(INADDR_ANY) 绑定网络信息的udp编程代码只能大致说明UDP的交互流程;不能体现在实战中UDP的用法及细节,下面聊一聊udp在实际应用中的用法,帮助萌新梳理思路:

首先了解这两个函数:

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
参数:
    sockfd:套接字
    buf:存放接收数据的缓存区
    len:接收长度
    flags:一般为0,不做详细解释,自信查询手册。
    src_addr:对端的网络信息
    addrlen:网络信息结构长度
接收到数据后,发送数据的源网络信息就会被保存在src_addr中,可以通过inet_ntoa(src_addr->sin_addr)获得对端ip; src_addr->sin_port获得对端端口号

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
参数:
    sockfd:套接字
    buf:存放发送数据的缓存区
    len:发送长度
    flags:一般为0,不做详细解释,自信查询手册。
    dest_addr:对端的网络信息
    addrlen:网络信息结构长度

接下来直接上代码,两台机器的ip为192.168.3.138和192.168.3.250 。

192.168.3.138的udp代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 

//该程序可以接收任意发往本机的数据,利用sendto将信息发送给192.168.3.250
int main(int argc, const char **argv)
{
    int fd = 0;
    struct sockaddr_in sin;
    
    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd < 0)
    {
        perror("create socket error !");
        return;
    }
    
    //绑定本地地址,用于接收数据
    sin.sin_family = AF_INET;
    sin.sin_port = htons(8888);
    sin.sin_addr.s_addr = inet_addr("192.168.0.138");
    bind(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in));
    
    while(1)
    {
        //设置目的端的网络信息,通过第三个参数告诉sendto发给谁!
        struct sockaddr_in client;
        client.sin_family = AF_INET;
        client.sin_port = htons(8888);
        client.sin_addr.s_addr = inet_addr("192.168.0.250");
        ret = sendto(fd, data, len, 0, (struct sockaddr *)&client, sizeof(struct sockaddr_in));
        if (ret < 0)
        {
            perror("send to heart pack erro : ");
            return;
        }
        //用于接收数据,套接字fd已经绑定了本地的网络信息,于是可以接收发给本机的数据(不仅仅接收192.168.3.250的信息)
        struct sockaddr_in src;
        uint8_t buf[1024] = {0};
        socklen_t len = sizeof(struct sockaddr_in);
        recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&src, &len);
        //打印发给本机的源ip地址和端口号
        printf("src ip : %s, src port : %d\n", inet_ntoa(src->sin_addr),src->sin_port);
    }
    
}

192.168.3.250的代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 

//该程序可以接收任意发往本机的数据,利用sendto将信息发送给192.168.3.250
int main(int argc, const char **argv)
{
    int fd = 0;
    struct sockaddr_in sin;
    
    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd < 0)
    {
        perror("create socket error !");
        return;
    }
    
    //绑定本地地址,用于接收数据
    sin.sin_family = AF_INET;
    sin.sin_port = htons(8888);
    sin.sin_addr.s_addr = inet_addr("192.168.0.250");
    bind(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in));
    
    while(1)
    {
        //用于接收数据,套接字fd已经绑定了本地的网络信息,于是可以接收发给本机的数据(不仅仅接收192.168.3.138的信息)
        struct sockaddr_in src;
        uint8_t buf[1024] = {0};
        socklen_t len = sizeof(struct sockaddr_in);
        recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&src, &len);
        //打印发给本机的源ip地址和端口号
        printf("src ip : %s, src port : %d\n", inet_ntoa(src->sin_addr),src->sin_port);
        
        //设置目的端的网络信息,通过第三个参数告诉sendto发给谁!
        struct sockaddr_in client;
        client.sin_family = AF_INET;
        client.sin_port = htons(8888);
        client.sin_addr.s_addr = inet_addr("192.168.0.138");
        ret = sendto(fd, data, len, 0, (struct sockaddr *)&client, sizeof(struct sockaddr_in));
        if (ret < 0)
        {
            perror("send to heart pack erro : ");
            return;
        }
    }
    
}

        上述代码应该已经很明白了,所以理论上来说udp没有所谓的服务器,客户端之说;上述代码的通讯方式类似于点对点通讯,发送的数据只能被指定的ip地址收到。

        既然这样为什么都说udp类似于广播呢?这是因为udp与通讯双方没有做连接动作,udp只是指定地址把数据散发出去,这个时候其他udp都可以接收这个数据,但是由于有指定地址,所以只有指定的地址才能接收该信息。类似于spi总线,主设备发送信号以后,所有从设备都能收到信号,从设备会判断是不是给自己的,如果不是就忽略。

你可能感兴趣的:(网络服务器,网络,udp,网络协议)