zoukankan      html  css  js  c++  java
  • Linux 下的 UDP 编程

    2019-10-14

    关键字:C 语言的 UDP 编程与实例


    UDP 连接是一种无连接的网络连接协议。

    Linux 下的 UDP 编程的函数接口与 TCP 差不了多远。在 UDP 通信模型中,也是以 C/S 模型来通信的。

    服务端的函数调用流程主要有以下几个:

    1、socket()

    2、bind()

    3、recvfrom() / sendto()

    4、close()

    客户端的函数调用流程主要有以下几个:

    1、socket()

    2、sendto() / recvfrom()

    3、close()

    socket()、bind() 函数:

    略,有需要的可以参阅 TCP 编程的文章。

    sendto() 函数:

    ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);

    这个函数与 TCP 编程里的 send() 很像,只不过多了两个参数 dest_addr 与 addrlen 而已。由于 UDP 是无连接式的网络通信,因此很容易猜到这多出来的两个参数和数据接收方的地址有关。

    参数 dest_addr 就是一个在填写时要用 sockaddr_in 结构体类型,使用时强转成 sockaddr 结构体类型的参数。用于填写数据接收方的 IP 地址、端口号与通信模式信息。

    参数 addrlen 就是结构体 dest_addr 的长度。

    recvfrom() 函数:

    ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);

    这个函数与上面 sendto() 几乎一样。

    参数 src_addr 与 addrlen 用于保存数据发送方的网络地址信息。

    实例

    客户端:

    int main(int argc, char *argv[])
    {
        int fd = -1;
        int port = 17173;
        
        struct sockadr_in sin;
        
        // 1. 创建 socket fd
        if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
        {
            perror("socket");
            exit(-1);
        }
        
        bzero(&sin, sizeof(sin));
        
        sin.sin_family = AF_INET;
        sin.sin_port = htons(port); // host to net,本地字节序转换成网络字节序。
        
        if(inet_pton(AF_INET, "192.168.77.3", (void *)&sin.sin_addr) != 1)
        {
            perror("inet_pton");
            exit(-1);
        }
        
        char buf[64];
        while(1)
        {
            bzero(buf, 64);
            if(fgets(buf, 64 - 1, stdin) == NULL)
            {
                perror("fgets");
                continue;
            }
            
            sendto(fd, buf, strlen(buf), 0, (struct socketaddr *)&sin, sizeof(sin));
            
            //退出判断。
        }
        
        close(fd);
        
        return 0;
    }

    服务端:

    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <errno.h>
    #include <stdlib.h>
    #include <strings.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netinet/ip.h>
    
    int main()
    {
        int fd = -1;
        struct sockaddr_in sin;
        
        if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
        {
            perror("socket");
            exit(-1);
        }
        
        //允许绑定地址与端口的快速重用。
        int b_reuse = 1;
        setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &b_reuse, sizeof(int));
        
        sin.sin_addr.s_addr = htonl(INADDR_ANY);
        
        if(bind(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0)
        {
            perror("bind");
            exit(-1);
        }
        
        char buf[64];
        struct sockaddr_in cin;
        socklen_t addrlen = sizeof(cin);
        while(1)
        {
            bzero(buf, 64);
            if(recvfrom(fd, buf, 64 - 1, 0, (struct sockaddr *)&cin, &addrlen) < 0)
            {
                perror("recvfrom");
                continue;
            }
            
            char ipv4[16];
            if(!inet_ntop(AF_INET, (void *)&cin.sin_addr, ipv4, sizeof(cin)))
            {
                perror("inet_ntop");
                exit(-1);
            }
            
            printf("received from(%s:%d), data:%s
    ", ipv4, ntohs(sin.sin_port), buf);
            
        }
        
        return 0;
    }

  • 相关阅读:
    Codeforces 813F Bipartite Checking 线段树 + 并查集
    Codeforces 263E Rhombus (看题解)
    Codeforces 173E Camping Groups hash
    Codeforces 311C Fetch the Treasure 取模意义下的最短路 (看题解)
    R 培训之 Table
    Docker命令详解
    Celery的实践指南
    Using Celery with Djang
    PostgreSQL
    改时区参考
  • 原文地址:https://www.cnblogs.com/chorm590/p/11638422.html
Copyright © 2011-2022 走看看