Linux应用 UDP网络编程

1、前言

1.1 定义

UDP 是一种无连接的传输协议,它不需要在通信之前建立连接,也不保证数据传输的可靠性。UDP 将数据打包成数据报进行传输,不进行数据分段和重组,因此传输效率较高。

1.2 应用场景

  • 实时性要求高的应用:由于 UDP 不保证数据传输的可靠性,适用于实时性要求高的应用,如音频/视频流的传输、在线游戏等。
  • 广播和多播通信:UDP 支持广播和多播通信,适用于需要向多个主机发送相同数据的场景。
  • 简单的数据传输:对于一些简单的数据传输场景,如 DNS 查询、SNMP 等,UDP 是一个较为合适的选择。

1.3 网络中的作用

在网络分层模型中,UDP 位于传输层,与 TCP 一起为应用层提供数据传输服务。

  • 为应用层提供无连接的数据传输服务:UDP 不需要建立连接,适用于一些实时性要求高、数据传输较简单的应用场景。
  • 提供数据报服务:UDP 将数据打包成数据报进行传输,不进行数据分段和重组,传输效率较高。
  • 支持广播和多播通信:UDP 支持向多个主机发送相同数据,适用于广播和多播通信场景。

2、常用接口

2.1 socket函数

创建一个套接字,用于后续的数据传输。

int socket(int domain, int type, int protocol);

入参:

  • domain:指定协议族,通常为 AF_INET(IPv4)或 AF_INET6(IPv6)。
  • type:指定套接字类型,通常为 SOCK_DGRAM 表示 UDP 套接字。
  • protocol:指定协议,通常为 0 表示使用默认协议。

返回值:

  • 成功时返回套接字描述符,失败时返回 -1

2.2 blind函数

将套接字绑定到特定的IP地址和端口号。

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

入参:

  • sockfd:套接字描述符,由socket()函数返回
  • addr:指向sockaddr结构体的指针,包含要绑定的IP地址和端口号信息
  • addrlensockaddr结构体的长度

返回值:

  • 成功时返回0,失败时返回-1

2.3 sendto函数

向指定地址发送数据。

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:目标地址的结构体指针,可以是 struct sockaddr_in 或 struct sockaddr_in6
  • addrlen:目标地址结构体的长度。

返回值:

  • 成功时返回发送的字节数,失败时返回 -1

2.4 recvfrom 函数

从指定的目标地址接收数据。

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:指向发送方地址信息的sockaddr结构体指针
  • addrlen:发送方地址结构体的长度

返回值:

  • 成功时返回接收的字节数,失败时返回-1

3、编程测试

3.1 一般编程步骤

UDP 服务器端编程流程:

  • 创建套接字:调用socket()函数创建一个UDP套接字。

  • 绑定地址:调用bind()函数将服务器端地址绑定到套接字上。

  • 接收数据:循环调用recvfrom()函数接收客户端发送的数据。

  • 处理数据:对接收到的数据进行处理,可以根据需求进行相应的逻辑操作。

  • 发送响应:根据处理结果,调用sendto()函数向客户端发送响应数据。

  • 关闭套接字:通信结束后,调用close()函数关闭套接字。

UDP 客户端编程流程:

  • 创建套接字:调用socket()函数创建一个UDP套接字。

  • 准备数据:准备要发送的数据,并将目标服务器地址信息填入sockaddr结构体中。

  • 发送数据:调用sendto()函数向服务器发送数据。

  • 接收响应:调用recvfrom()函数接收服务器端的响应数据。

  • 处理响应:对接收到的响应数据进行处理,可以根据需求进行相应的逻辑操作。

  • 关闭套接字:通信结束后,调用close()函数关闭套接字。

3.2 服务器编程

编写服务器代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

#define PORT 8888
#define BUF_SIZE 1024

int main() 
{
    int sockfd;
    struct sockaddr_in server_addr, client_addr;
    char buffer[BUF_SIZE];

    // 创建 UDP 套接字
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    // 绑定服务器地址和端口
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(PORT);
    bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));

    printf("UDP Server listening on port %d...\n", PORT);

    socklen_t len = sizeof(client_addr);
    
    // 接收数据
    recvfrom(sockfd, buffer, BUF_SIZE, 0, (struct sockaddr*)&client_addr, &len);
    printf("Received from client: %s\n", buffer);

    // 回复客户端数据
    sendto(sockfd, "Message received", strlen("Message received"), 0, (struct sockaddr*)&client_addr, len);

    close(sockfd);
    return 0;
}

3.3 客户端编程

编写客户端代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

#define PORT 8888
#define SERVER_IP "127.0.0.1"
#define BUF_SIZE 1024

int main() 
{
    int sockfd;
    struct sockaddr_in server_addr;
    char buffer[BUF_SIZE] = "msg from client";

    // 创建 UDP 套接字
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    // 设置服务器地址和端口
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
    server_addr.sin_port = htons(PORT);

    // 发送数据到服务器
    sendto(sockfd, buffer, strlen(buffer), 0, (struct sockaddr*)&server_addr, sizeof(server_addr));

    // 接收服务器回复的数据
    recvfrom(sockfd, buffer, BUF_SIZE, 0, NULL, NULL);
    printf("Server replied: %s\n", buffer);

    close(sockfd);
    return 0;
}

3.4 测试

开启两个终端进行测试,先开启服务器,再开启客户端,测试结果如下:

4、总结

本文讲解了UDP的定义以及应用场景,列出了编程中常用的接口,最后编写程序进行测试。

相关推荐

  1. linux网络----UDP编程

    2024-04-04 06:08:02       35 阅读
  2. 网络编程】-- 04 UDP

    2024-04-04 06:08:02       39 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-04 06:08:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-04 06:08:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-04 06:08:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-04 06:08:02       20 阅读

热门阅读

  1. DockerFile启动jar程序

    2024-04-04 06:08:02       12 阅读
  2. Sass学习记录

    2024-04-04 06:08:02       14 阅读
  3. NRM详解

    2024-04-04 06:08:02       18 阅读
  4. SpringBoot如何集成nacos,用于服务发现和配置管理

    2024-04-04 06:08:02       13 阅读
  5. 【Next.js】连接 MongoDB 实现基本的接口

    2024-04-04 06:08:02       15 阅读
  6. MongoDB聚合运算符:$lte

    2024-04-04 06:08:02       14 阅读
  7. 金融出海机遇与挑战

    2024-04-04 06:08:02       14 阅读
  8. Linux初学(十二)AWK进阶

    2024-04-04 06:08:02       14 阅读
  9. WebGL BabylonJs 如何切换相机

    2024-04-04 06:08:02       15 阅读
  10. 针孔相机、鱼眼相机、全景相机

    2024-04-04 06:08:02       12 阅读