【C++高并发服务器WebServer】-16:UDP简单实现

server/2025/2/11 0:28:02/

在这里插入图片描述

本文目录

  • 一、UDP通信流程
  • 二、UDP API
    • 2.1 sendto()
    • 2.2 recvfrom()

一、UDP通信流程

UDP通信的流程比较简单,下面这张图可以总结。
在这里插入图片描述

二、UDP API

2.1 sendto()

UDP相关头文件如下。

#include <sys/types.h>
#include <sys/socket.h>
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);

sockfd:一个有效的UDP套接字文件描述符,该套接字已经通过socket函数创建。
buf:指向要发送数据的缓冲区的指针。
len:要发送的数据的长度(字节数)。
flags:通常设置为0。也可以设置特定的标志来改变发送的行为,如MSG_DONTROUTE(绕过路由器)。
dest_addr:指向sockaddr结构的指针,该结构包含了目的地址信息。这个地址可以是IPv4或IPv6地址,具体取决于套接字的地址族(AF_INET或AF_INET6)。
addrlen:dest_addr结构的长度。这个长度应该与dest_addr指向的结构的大小相匹配。

成功时,sendto函数返回发送的字节数。出错时,返回-1,并设置errno以指示错误类型。

简单实现demo如下所示。

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>int main() {int sockfd;struct sockaddr_in servaddr;char *message = "Hello, UDP server!";size_t len = strlen(message) + 1;ssize_t sent;// 创建UDP套接字sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0) {perror("socket creation failed");exit(EXIT_FAILURE);}// 设置服务器地址和端口memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(12345); // 服务器端口号inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr); // 服务器IP地址// 发送数据sent = sendto(sockfd, message, len, 0, (const struct sockaddr *)&servaddr, sizeof(servaddr));if (sent < 0) {perror("sendto failed");close(sockfd);exit(EXIT_FAILURE);}printf("Sent %ld bytes\n", (long)sent);// 关闭套接字close(sockfd);return 0;
}

2.2 recvfrom()

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

sockfd:一个有效的UDP套接字文件描述符,该套接字已经通过 socket 函数创建。
buf:指向用于存储接收数据的缓冲区的指针。
len:缓冲区的长度(字节数)。
flags:通常设置为0。也可以设置特定的标志来改变接收的行为,如 MSG_DONTWAIT(非阻塞接收)。
src_addr:指向 sockaddr 结构的指针,该结构用于存储发送方的地址信息。如果不需要地址信息,可以设置为NULL。
addrlen:指向变量的指针,该变量在调用前应初始化为 src_addr 结构的长度。调用成功后,该变量将被更新为实际接收到的地址的长度。

成功时,recvfrom 函数返回接收到的字节数。出错时,返回 -1,并设置 errno 以指示错误类型。

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>#define BUF_SIZE 1024int main() {int sockfd;struct sockaddr_in servaddr, cliaddr;char buffer[BUF_SIZE];ssize_t received;socklen_t addrlen;// 创建UDP套接字sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0) {perror("socket creation failed");exit(EXIT_FAILURE);}// 设置服务器地址和端口memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(12345); // 服务器端口号// 绑定套接字if (bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {perror("bind failed");close(sockfd);exit(EXIT_FAILURE);}// 接收数据addrlen = sizeof(cliaddr);received = recvfrom(sockfd, buffer, BUF_SIZE, 0, (struct sockaddr *)&cliaddr, &addrlen);if (received < 0) {perror("recvfrom failed");close(sockfd);exit(EXIT_FAILURE);}printf("Received %ld bytes from %s:%d\n", (long)received,inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));// 关闭套接字close(sockfd);return 0;
}

http://www.ppmy.cn/server/166615.html

相关文章

2.攻防世界 backup

题目描述中提示&#xff0c;备份文件 进入题目页面如下 通用备份文件后缀名 .bak&#xff1a;这是最常见的备份文件后缀名之一&#xff0c;表示某个文件的备份版本。 .old&#xff1a;表示文件的旧版本或备份&#xff0c;通常用于系统更新时保存旧文件。 .backup&#xff1a;…

如何使用 Python 高效操作 Word 文档:python-docx 和 comtypes 介绍与实践

如何使用 Python 高效操作 Word 文档&#xff1a;python-docx 和 comtypes 介绍与实践 在日常的办公自动化任务中&#xff0c;Python 提供了一些强大的库来帮助我们高效地操作 Word 文档。常用的库包括 python-docx 和 comtypes&#xff0c;它们可以分别用于创建、修改、格式化…

DeepSeek R1 Distill Llama 70B(免费版)API使用详解

DeepSeek R1 Distill Llama 70B&#xff08;免费版&#xff09;API使用详解 在人工智能领域&#xff0c;随着技术的不断进步&#xff0c;各种新的模型和应用如雨后春笋般涌现。今天&#xff0c;我们要为大家介绍的是OpenRouter平台上提供的DeepSeek R1 Distill Llama 70B&…

网络基础之IP

从网络安全的角度分析 IP 的作用及可能存在的风险 在当代网络威胁的背景下&#xff0c;IP地址&#xff08;Internet Protocol Address&#xff09; 是网络通信的核心标识符之一。它不仅标识计算机或设备在整个网络中的位置&#xff0c;还通过物理特性&#xff08;如延迟、噪声…

【ORACLE】case when语句的语法陷阱

前言 前一段时间在迁移Oracle到一个openGauss系数据 库时&#xff0c;发现存储过程里有一条SQL报错&#xff0c;简化后如下 gaussdb# select gaussdb-# case when 11 then 1 end case gaussdb-# from dual; ERROR: syntax error at or near "case" LINE 2: case w…

Unity项目接入xLua的一种流程

1. 导入xlua 首先导入xlua&#xff0c;这个不用多说 2. 编写C#和Lua交互脚本 基础版本&#xff0c;即xlua自带的版本 using System.Collections; using System.Collections.Generic; using UnityEngine; using XLua; using System; using System.IO;[Serializable] public…

【CPP】CPP经典面试题

文章目录 引言1. C 基础1.1 C 中的 const 关键字1.2 C 中的 static 关键字 2. 内存管理2.1 C 中的 new 和 delete2.2 内存泄漏 3. 面向对象编程3.1 继承和多态3.2 多重继承 4. 模板和泛型编程4.1 函数模板4.2 类模板 5. STL 和标准库5.1 容器5.2 迭代器 6. 高级特性6.1 移动语义…

网络工程师 (23)OSI模型层次结构

前言 OSI&#xff08;Open System Interconnect&#xff09;模型&#xff0c;即开放式系统互联模型&#xff0c;是一个完整的、完善的宏观模型&#xff0c;它将计算机网络体系结构划分为7层。 OSI七层模型 1. 物理层&#xff08;Physical Layer&#xff09; 功能&#xff1a;负…