Linux _UDP 浅解

UDP通信

  1. TCP与UDP
    当使用网络套接字通信时,
    套接字的“域”都取AF_INET;
    套接字的type:
    SOCK_STREAM 此时,默认使用TCP协议进行通信。
    SOCK_DGRAM 此时,默认使用UDP协议进行通信。

    TCP通信,是一个有序的、可靠的、面向连接的
    UDP通信,是不保证有序到达的数据报服务。(在局域网内,使用UDP已很可靠)

  2. 使用UDP通信
    与TCP通信使用上的区别:
    1)创建套接字时的type(参数2)不同。
    TCP通信,使用SOCK_STREAM
    UDP通信,使用SOCK_DGRAM

    2)发送数据和接收数据时,使用的接口不同
    TCP通信,发送数据,使用write(或send)
    接收数据,使用read(或recv)
    UDP特性,发送数据,使用sendto
    接收数据,服务器端使用recvfrom
    客户端使用recv

    3)不需要使用listen
    4)不需要先建立连接(TCP客户端和服务器端分别使用connect和receive建立连接)

    步骤总结:
    基于UDP的网络套接字通信
    服务器端
    (1) 创建一个网络套接字
    (2) 设置服务器地址
    (3) 绑定该套接字,使得该套接字和对应的端口关联起来
    (4) 循环处理客户端请求
    使用recvfrom等待接收客户端发送的数据
    使用sendto发送数据至客户端

    客户端
    (1) 创建一个套接字
    (2) 设置服务器地址
    (3) 使用sendto向服务器端(接收端)发送数据
    (4) 使用recv接受数据

  3. sendto与recvfrom、recv
    1) sendto
    功能:UDP服务器或客户端用于发送数据
    原型:int sendto (int sockfd, // 套接字
    void *buff, // 发送缓存区
    size_t len, // 发送缓冲区的长度
    init flags, // 标志,一般取0
    struct sockaddr *to, // 目的主机地址
    socklen_t tolen // 目的主机地址长度
    );
    返回值:成功,返回实际发送数据的字节数
    失败,返回-1

    2) recvfrom
    功能:UDP服务器用于接收数据
    原型: 与sendto类似。
    int recvfrom (int sockfd, // 套接字
    void *buff, // 接收缓存区
    size_t len, // 接受缓冲区的长度
    init flags, // 标志,一般取0
    struct sockaddr *to, // 源主机地址
    socklen_t *tolen // 源主机地址长度
    );
    注意:参数6必须要初始化为对应地址的长度!
    3) recv
    功能:UDP客户端用于接收数据
    原型: ssize_t recv (int sockfd, void *buf, size_t len, int flags);
    注意: 该调用的参数不需要指定地址。
    因为当使用udp时,对应的套接字被自动绑定在一个短暂的动态的端口上。

  4. 实例
    server1.c / client1.c 服务器接收、客户端发送
    server2.c / client2.c 服务器收发、客户方发送、接收。

demo
server1.c

#include <sys/un.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>

#define BUFF_SIZE 1024

int main(void)
{
    int server_sockfd;
    int client_sockfd;
    char ch;
    int ret;
    int recv_len;
    char buff[BUFF_SIZE];

     //”√”⁄UNIXœµÕ≥ƒ⁄≤øÕ®–≈µƒµÿ÷∑£¨ struct sockaddr_un
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    int client_addr_len;

    server_sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    // …Ë÷√∑˛ŒÒ∆˜µÿ÷∑
    server_addr.sin_family = AF_INET;  //µÿ÷∑µƒ”Ú£¨œ‡µ±”⁄µÿ÷∑µƒ¿‡–Õ, AF_UNIX±Ì æµÿ÷∑Œª”⁄UNIXœµÕ≥ƒ⁄≤ø
    server_addr.sin_addr.s_addr = INADDR_ANY;  //inet_addr("10.10.0.9");
    server_addr.sin_port = htons(9000);

    // ∞Û∂®∏√Ã◊Ω”◊÷£¨ πµ√∏√Ã◊Ω”◊÷∫Õ∂‘”¶µƒœµÕ≥Ã◊Ω”◊÷Œƒº˛πÿ¡™∆¿¥°£
    ret = bind(server_sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
    if (ret == -1) {
        perror("bind");
        exit(1);
    }

    // ¥¥Ω®Ã◊Ω”◊÷∂”¡–£¨ ±£¥ÊΩ¯»Î∏√∑˛ŒÒ∆˜µƒøÕªß∂À«Î«Û°£
    //ret = listen(server_sockfd, 5);

    // —≠ª∑¥¶¿ÌøÕªß∂À«Î«Û
    while (1) {

        printf("server waiting\n");

        // µ»¥˝≤¢Ω” ’øÕªß∂À«Î«Û
        //client_sockfd = accept(server_sockfd,  (struct sockaddr*)&client_addr, &client_addr_len);
              recv_len = recvfrom(server_sockfd, buff, sizeof(buff) , 0, 
                                           (struct sockaddr*)&client_addr, &client_addr_len);
        if (recv_len < 0) {
            perror("recvfrom");
            exit(errno);
        }

        printf("received: %s\n", buff); 
    }

    close(server_sockfd);

    return 0;   
}

client1.c

#include <sys/un.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>

#define BUFF_SIZE 1024

int main(void)
{
    int sockfd;
    struct sockaddr_in server_addr;
    int ret;
    int c;
    char buff[BUFF_SIZE];

    // ¥¥Ω®“ª∏ˆÃ◊Ω”◊÷
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    // …Ë÷√∑˛ŒÒ∆˜µÿ÷∑
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("10.10.0.9");
    server_addr.sin_port = htons(9000);

       // œÚ∑˛ŒÒ∆˜∑¢ÀÕ ˝æ›
       strcpy(buff, "hello world");
       ret = sendto(sockfd, buff, strlen(buff) + 1, 0, (struct sockaddr*)&server_addr, sizeof(server_addr));
    if (ret == -1) {
        perror("sendto");
        exit(errno);
    }

    printf("ret = %d\n", ret);


    return 0;   
}

server2.c

#include <sys/un.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>

#define BUFF_SIZE 1024

static void str2up(char *str)
{
    while(*str) {
        if (*str >= 'a'  && *str <= 'z') {
            *str = *str - 'a' + 'A';
        }

        str++;
    }
}

int main(void)
{
    int server_sockfd;
    int client_sockfd;
    char ch;
    int ret;
    int recv_len;
    int send_len;
    char buff[BUFF_SIZE];

     //”√”⁄UNIXœµÕ≥ƒ⁄≤øÕ®–≈µƒµÿ÷∑£¨ struct sockaddr_un
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    int client_addr_len;

    server_sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    // …Ë÷√∑˛ŒÒ∆˜µÿ÷∑
    server_addr.sin_family = AF_INET;  //µÿ÷∑µƒ”Ú£¨œ‡µ±”⁄µÿ÷∑µƒ¿‡–Õ, AF_UNIX±Ì æµÿ÷∑Œª”⁄UNIXœµÕ≥ƒ⁄≤ø
    server_addr.sin_addr.s_addr = INADDR_ANY;  //inet_addr("10.10.0.9");
    server_addr.sin_port = htons(9000);

    // ∞Û∂®∏√Ã◊Ω”◊÷£¨ πµ√∏√Ã◊Ω”◊÷∫Õ∂‘”¶µƒœµÕ≥Ã◊Ω”◊÷Œƒº˛πÿ¡™∆¿¥°£
    ret = bind(server_sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
    if (ret == -1) {
        perror("bind");
        exit(1);
    }

    // ¥¥Ω®Ã◊Ω”◊÷∂”¡–£¨ ±£¥ÊΩ¯»Î∏√∑˛ŒÒ∆˜µƒøÕªß∂À«Î«Û°£
    //ret = listen(server_sockfd, 5);

    // —≠ª∑¥¶¿ÌøÕªß∂À«Î«Û
    while (1) {

        printf("server waiting\n");

        // µ»¥˝≤¢Ω” ’øÕªß∂À«Î«Û
        //client_sockfd = accept(server_sockfd,  (struct sockaddr*)&client_addr, &client_addr_len);
              recv_len = recvfrom(server_sockfd, buff, sizeof(buff) , 0, 
                                           (struct sockaddr*)&client_addr, &client_addr_len);
        if (recv_len < 0) {
            perror("recvfrom");
            exit(errno);
        }

        printf("received: %s\n", buff); 

        str2up(buff);
        send_len = sendto(server_sockfd, buff, strlen(buff)+1, 0,
                                (struct sockaddr*)&client_addr, client_addr_len);
        if (send_len == -1) {
            perror("sendto");
            exit(errno);
        }

        //printf("send_len=%d\n", send_len);                  
    }

    close(server_sockfd);

    return 0;   
}

client2.c

#include <sys/un.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>

#define BUFF_SIZE 1024

int main(void)
{
    int sockfd;
    struct sockaddr_in server_addr;
    int ret;
    int c;
    char buff[BUFF_SIZE];
    socklen_t addr_len;

    // ¥¥Ω®“ª∏ˆÃ◊Ω”◊÷
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    // …Ë÷√∑˛ŒÒ∆˜µÿ÷∑
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("10.10.0.99");
    server_addr.sin_port = htons(9000);

       // œÚ∑˛ŒÒ∆˜∑¢ÀÕ ˝æ›
       strcpy(buff, "hello world");
       ret = sendto(sockfd, buff, strlen(buff) + 1, 0, (struct sockaddr*)&server_addr, sizeof(server_addr));
    if (ret == -1) {
        perror("sendto");
        exit(errno);
    }

    printf("send %d bytes\n", ret);

    ret = recv(sockfd, buff, sizeof(buff), 0);
    if (ret == -1) {
        perror("recvfrom");
        exit(errno);
    }

    printf("received %d bytes\n", ret);
    printf("received: %s\n", buff); 

    return 0;   
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值