Linux_实现UDP网络通信
目录
1、实现服务器的逻辑
1.1 socket
1.2 bind
1.3 recvfrom
1.4 sendto
1.5 服务器代码
2、实现客户端的逻辑
2.1 客户端代码
3、实现通信
结语
前言:
在Linux下,实现传输层协议为UDP的套接字进行网络通信,网络层协议为IPv4,需要用到的接口有以下4个:socket、bind、recvfrom、sendto。具体实现方法:在云服务器上创建一个服务器进程和一个客户端进程,让客户端向服务器发送消息,并且服务器收到消息后可以反馈给对方。
示意图如下:

1、实现服务器的逻辑
按照以下函数的调用顺序,即可实现服务器方的UDP通信。
1.1 socket
首先明确使用IPv4协议和UDP协议后,先调用接口socket,让其返回一个网络文件描述符给到我们,socket函数介绍如下:
#include <sys/types.h>
#include <sys/socket.h>int socket(int domain, int type, int protocol);
//domain表示网络协议族,AF_INET为IPv4,AF_INET6为IPv6
//type表示传输层协议,SOCK_STREAM为TCP,SOCK_DGRAM为UDP
//protocol表示指定特定的协议,一般前两个参数的协议足矣,这里填0即可//调用成功返回一个类型文件描述符的网络描述符,失败返回-1
1.2 bind
定义一个struct sockaddr_in类型的变量,该变量的作用是为调用bind接口做准备,该变量里面有3个信息需要填写,分别是:1、传输层协议,2、为该进程设置的端口号,3、该主机的IP地址。其中,端口号和IP地址需要对其转换成大端字节序,因为网络规定传输的数据采用大端字节序传输,这里介绍两个接口可以帮助我们直接将端口号和IP转换成大端字节序,接口介绍如下:
#include <arpa/inet.h>uint16_t htons(uint16_t hostshort);//常用来转换端口号
//将主机字节序转换成网络字节序并返回#include <arpa/inet.h> unsigned long inet_addr(const char *cp);//常用来转换IP地址
//如果cp指向的是IP地址的字符串形式,那么会将其转换为网络字节序的IP地址
//并且以无符号的长整型返回
待struct sockaddr_in类型的变量的字段填写完毕后,下一步就是进行绑定操作,绑定的目的是将socket返回的网络描述符与struct sockaddr_in类型的变量进行绑定,即可以通过网络描述符来找到对应的ip地址以及端口号,简单来说,通过网络描述符就能找到对应主机的对应进程。
接着就是调用bind接口进行绑定了,bind接口介绍如下:
int bind(int socket, const struct sockaddr *address,socklen_t address_len);
//socket表示要绑定的网络描述符
//address表示指向struct sockaddr类型的变量
//address_len表示address指向变量的大小//调用成功返回0,失败返回-1
1.3 recvfrom
recvfrom接口有点类似文件操作中的read接口,都带有接收的意思。recvfrom接口用于从网络描述符中读取对方主机发送的数据,并且还可以将对方主机的地址信息(IP和端口号)给记录下来,该接口的介绍如下:
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
//sockfd表示读取的网络描述符
//buf表示存放读取数据的目标缓冲区
//len表示期望读取内容的大小
//flag表示设置该函数的模式,比如阻塞或非阻塞,通常设为0表阻塞
//src_addr是个输出型参数,用于保存发送方的地址信息
//addrlen表示src_addr指向变量的大小//成功返回接收的字节数,若sockfd关闭返回0,失败返回-1
1.4 sendto
如果说recvfrom接口类似read接口,那么sendto就好比write接口,他能够往网络文件描述符内写入数据,即发送方就是调用sendto接口向接收方发送数据,sendto和recvfrom相互搭配实现网络通信。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表示要发送数据的长度
//flag表示设置该函数的模式,比如阻塞或非阻塞,通常设为0表阻塞
//dest_addr指向的结构体里包含接收方的IP和端口号,依靠他们才能找到接收方
//addrlen表示dest_addr指向结构体的大小
1.5 服务器代码
将服务器封装成一个类,并把服务器的端口号、ip地址、网络描述符作为该类的成员变量,这样就可以对上述功能逻辑进行分层了,服务器类代码如下:
#pragma once#include <iostream>
#include <string>
#include <strings.h>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstdio>
#include <unistd.h>
using namespace std;uint16_t defaultport = 8080;
std::string defaultip = "0.0.0.0";
const int size = 1024;class UdpServer{
public:UdpServer(const uint16_t &port = defaultport, const std::string &ip = defaultip):sockfd_(0), port_(port), ip_(ip){}void Init(){// 1. 创建udp socketsockfd_ = socket(AF_INET, SOCK_DGRAM, 0); printf("socket create success, sockfd: %d\n", sockfd_);// 2. bind socketstruct sockaddr_in local;bzero(&local, sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(port_); local.sin_addr.s_addr = inet_addr(ip_.c_str()); bind(sockfd_, (const struct sockaddr *)&local, sizeof(local));printf("bind success, errno: %d, \err string: %s\n", errno, strerror(errno));}void Run() // 对代码进行分层{char inbuffer[size];while(true){struct sockaddr_in client;socklen_t len = sizeof(client);//服务器先接收消息ssize_t n = recvfrom(sockfd_, inbuffer, sizeof(inbuffer) - 1,0, (struct sockaddr*)&client, &len);cout<<"客户端说:"<<inbuffer<<endl;inbuffer[n] = 0;std::string info = inbuffer;std::string echo_string = "服务器的回答:"+info;//再反馈消息sendto(sockfd_, echo_string.c_str(), echo_string.size(), 0, (const sockaddr*)&client, len);}}~UdpServer(){if(sockfd_>0) close(sockfd_);//关闭描述符}
private:int sockfd_; // 网路文件描述符std::string ip_; // ip地址uint16_t port_; // 服务器端口号
};
该服务器的逻辑是先接收客户端发送的消息,然后利用recvfrom函数保存客户端的地址信息,再使用sendto函数对客户端进行信息的反馈。
2、实现客户端的逻辑
客户端逻辑和服务器逻辑几乎一样,第一步必须调用socket创建网络描述符,但是第二步客户端不需要进行bind绑定,因为服务器之所以需要绑定是因为服务器必须手动自定义一个端口号,目的就是要让该端口号可见,以便让客户端知道该端口号,这样客户端才能通过该端口号定位服务器。而客户端不需要自定义端口号,因为客户端的主要任务是给服务器发送信息,这个过程服务器是不需要知道客户端的端口号也可以接收客户端的信息,因此客户端的端口号只需要保证其唯一性即可,即交给操作系统来生成,当首次发送数据的时候操作系统就会为客户端生成端口号。
2.1 客户端代码
客户端代码如下:
#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>using namespace std;void Usage(std::string proc)
{std::cout << "\n\rUsage: " << proc << " serverip serverport\n"<< std::endl;
}// ./udpclient serverip serverport
int main(int argc, char *argv[])
{if (argc != 3){Usage(argv[0]);exit(0);}//从命令行参数拿到ip地址和端口号std::string serverip = argv[1];uint16_t serverport = std::stoi(argv[2]);struct sockaddr_in server;bzero(&server, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(serverport); //转换网络字节序server.sin_addr.s_addr = inet_addr(serverip.c_str());//转换网络字节序// 1. socket拿到网络描述符int sockfd = socket(AF_INET, SOCK_DGRAM, 0);socklen_t len = sizeof(server);string message;char buffer[1024];while (true){cout << "Please Enter@ ";getline(cin, message);//2. 向服务器发送信息sendto(sockfd, message.c_str(), message.size(), 0, (struct sockaddr *)&server, len);struct sockaddr_in temp;socklen_t len = sizeof(temp);//3. 打印来自服务器的信息recvfrom(sockfd, buffer, 1023, 0, (struct sockaddr*)&temp, &len);cout << buffer << endl;}close(sockfd);//关闭文件描述符return 0;
}
3、实现通信
实现通信的前提是让服务器以进程的形式跑起来,然后再让客户端也以进程的形式跑起来,因为网络通信的本质就是进程间通信,而上述代码中客户端本身就是在main函数中执行的,所以此时客户端可以直接运行,但是服务器还只是个类,因此现在只需要用服务器类实现一个main函数,即可完成两个进程的运行。
服务器进程代码如下:
#include "UDPser.hpp"
#include <memory>
#include <cstdio>void Usage(std::string proc)
{std::cout << "\n\rUsage: " << proc << " port[1024+]\n" << std::endl;
}// ./udpserver port
int main(int argc, char *argv[])
{if(argc != 2){Usage(argv[0]);exit(0);}//从命令行参数拿到端口号uint16_t port = std::stoi(argv[1]);std::unique_ptr<UdpServer> svr(new UdpServer(port));svr->Init();svr->Run();return 0;
}
运行结果:

从结果可以看到目前可以正常的进行客户端与服务器之间的通信。
结语
以上就是关于实现UDP网络通信的讲解,实现UDP的核心在于对套接字的理解以及相关接口的逻辑使用,其实只需要记住只要涉及到网络通信,那么socket和bind函数是必须在最开始就调用的。
最后如果本文有遗漏或者有误的地方欢迎大家在评论区补充,谢谢大家!!
相关文章:
Linux_实现UDP网络通信
目录 1、实现服务器的逻辑 1.1 socket 1.2 bind 1.3 recvfrom 1.4 sendto 1.5 服务器代码 2、实现客户端的逻辑 2.1 客户端代码 3、实现通信 结语 前言: 在Linux下,实现传输层协议为UDP的套接字进行网络通信,网络层协议为IPv4&am…...
C# 代理模式
栏目总目录 概念 代理模式是一种结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。在代理模式中,我们创建一个具有现有对象(称为“真实对象”或“被代理对象”)相同功能的代理对象。代理对象可以在客户端和目标对…...
【1】Python机器学习之基础概念
1、什么是机器学习 最早的机器学习应用——垃圾邮件分辨 传统的计算机解决问题思路: 编写规则,定义“垃圾邮件”,让计算机执行对于很多问题,规则很难定义规则不断变化 机器学习在图像识别领域的重要应用: 人脸识别…...
HashMap源码解析
目录 一:put方法流程 二:get方法 三:扩容机制 一:put方法流程 public V put(K key, V value) {return putVal(hash(key), key, value, false, true); }final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {No…...
[Javascript】前端面试基础3【每日学习并更新10】
Web开发中会话跟踪的方法有那些 cookiesessionurl重写隐藏inputip地址 JS基本数据类型 String:用于表示文本数据。Number:用于表示数值,包括整数和浮点数。BigInt:用于表示任意精度的整数。Boolean:用于表示逻辑值…...
C++自定义字典树结构
代码 #include <iostream> using namespace std;class TrieNode { public:char data;TrieNode* children[26];bool isTerminal;TrieNode(char ch){data ch;for (int i 0; i < 26; i){children[i] NULL;}isTerminal false;} }; class Trie { public:TrieNode* ro…...
dockerfile部署wordpress
1.将容器直接提交成镜像 [rootlocalhost ~]# docker commit 8ecc7f6b9c12 nginx:1.1 sha256:9a2bb94ba6d8d952527df616febf3fbc8f842b3b9e28b7011b50c743cd7b233b [rootlocalhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx …...
CSS(二)——CSS 背景
CSS 背景 CSS 背景属性用于定义HTML元素的背景。 CSS 背景属性 Property描述background简写属性,作用是将背景属性设置在一个声明中。background-attachment背景图像是否固定或者随着页面的其余部分滚动。background-color设置元素的背景颜色。background-image把…...
开机出现grub无法进入系统_电脑开机出现grub解决方法
最近有小伙伴问我电脑开机出现grub无法进入系统怎么回事?电脑开机出grub的情况有很多,电脑上安装了Linux和Win10双系统,但是由于格式化删除了Linux之后,结果win10开机了之后,直接显示grub>,无法…...
uboot 设置bootargs配置内核网络挂载根文件系统
uboot 设置bootargs配置内核网络挂载根文件系统 uboot设置bootargs env set bootargs "mem256M consolettyAMA0,115200 root/dev/nfs init/linuxrc nfsrootnfs主机地址:nfs路径/busybox/rootfs_glibc_arm64,prototcp rw nfsvers3 rootwait ip板子地址:nfs主机地址:网关:2…...
Vue3+.NET6前后端分离式管理后台实战(三十一)
1,Vue3.NET6前后端分离式管理后台实战(三十一)...
22集 如何minimax密钥和groupid-《MCU嵌入式AI开发笔记》
22集 如何获取minimax密钥和groupid-《MCU嵌入式AI开发笔记》 minimax密钥获取 https://www.minimaxi.com/platform 进入minimax网站,注册登录后,进入“账户管理”, 然后再点击“接口密钥”,然后再点击“创建新的密钥”。 之…...
决策树的概念
决策树的概念 决策树是一种监督学习算法,主要用于分类任务。它通过构建一棵树结构模型来进行预测,其中每个内部节点表示一个特征属性上的判断条件,每条边代表一个判断结果对应的分支,而叶节点则代表最终的类别标签。 应用领域 …...
C++《类和对象》(中)
一、 类的默认成员函数介绍二、构造函数 构造函数名与类同名内置类型与自定义类型析构函数拷贝构造函数 C《类和对象》(中) 一、 类的默认成员函数介绍 默认成员函数就是⽤⼾没有显式实现,编译器会⾃动⽣成的成员函数称为默认成员函数。 那么我们主要学习的是1&…...
SpringBoot中JSR303校验
JSR是 Java EE 的一种标准,用于基于注解的对象数据验证。在Spring Boot应用中,你可以通过添加注解直接在POJO类中声明验证规则。这样可以确保在使用这些对象进行操作之前,它们满足业务规则。个人认为非常有用的,因为它减少了代码中…...
图像数据增强方法概述
图像数据增强方法概述 1. 什么是图像数据增强技术?2. 图像数据增强技术分类2.1 几何变换Python 示例代码 2.2 颜色变换2.3 噪声添加 3. 参考文献 1. 什么是图像数据增强技术? 基础概念:图像增强技术是计算机视觉和图像处理领域中的一个关键技术,主要用…...
【学习笔记】无人机系统(UAS)的连接、识别和跟踪(五)-无人机跟踪
目录 引言 5.3 无人机跟踪 5.3.1 无人机跟踪模型 5.3.2 无人机位置报告流程 5.3.3 无人机存在监测流程 引言 3GPP TS 23.256 技术规范,主要定义了3GPP系统对无人机(UAV)的连接性、身份识别、跟踪及A2X(Aircraft-to-Everyth…...
分享从零开始学习网络设备配置--任务6.1 实现计算机的安全接入
项目描述 随着网络技术的发展和应用范围的不断扩大,网络已经成为人们日常生活中必不可少的一部分。园区网作为给终端用户提供网络接入和基础服务的应用环境,其存在的网络安全隐患不断显现出来,如非人为的或自然力造成的故障、事故;…...
双向链表(C语言版)
1. 双向链表的结构 注意:这里的“带头”跟单链表的“头结点”是两个概念,实际上在单链表阶段称呼不太严谨,但是为了更好地理解就直接称为单链表的头结点。带头链表里的头结点,实际为“哨兵位”,哨兵位结点不存储任何有…...
【算法/学习】前缀和差分
前缀和&&差分目录 1. 前缀和的概念及作用 🌈概念 🌈用途 🌙一维前缀和 🌙二维前缀和 2. 差分的概念及用途 🌈概念: 🌈用途 🌙一维差分 🌙二维差分 1. …...
基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
Unity UGUI Button事件流程
场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...
大数据治理的常见方式
大数据治理的常见方式 大数据治理是确保数据质量、安全性和可用性的系统性方法,以下是几种常见的治理方式: 1. 数据质量管理 核心方法: 数据校验:建立数据校验规则(格式、范围、一致性等)数据清洗&…...
Canal环境搭建并实现和ES数据同步
作者:田超凡 日期:2025年6月7日 Canal安装,启动端口11111、8082: 安装canal-deployer服务端: https://github.com/alibaba/canal/releases/1.1.7/canal.deployer-1.1.7.tar.gz cd /opt/homebrew/etc mkdir canal…...
Ray框架:分布式AI训练与调参实践
Ray框架:分布式AI训练与调参实践 系统化学习人工智能网站(收藏):https://www.captainbed.cn/flu 文章目录 Ray框架:分布式AI训练与调参实践摘要引言框架架构解析1. 核心组件设计2. 关键技术实现2.1 动态资源调度2.2 …...
