UDP网络编程套接
目录
本文核心
预备知识
1.端口号
认识TCP协议
认识UDP协议
网络字节序
socket编程接口
sockaddr结构
UDP套接字编程
服务端
客户端
TCP与UDP传输的区别
可靠性:
传输方式:
用途:
头部开销:
速度:
linux相关的指令操作
ip地址转化函数
本文核心
预备知识
1.端口号
pid是进程管理的模块,纳入到网络板块不符合低耦合
万一进程版块出错,那么就会出现牵一发而动全身的效果
端口号:c:客户端 s:服务器




基于ip+端口的通信方式称为socket
进程如何绑定端口号呢?
通过哈希运算,把pcb绑定到特定的哈希表中

认识TCP协议
认识UDP协议
网络字节序
socket编程接口
基于ip+端口当通信方式称为socket(套接字)
套接字(Socket)是计算机网络通信中一个抽象层,它提供了进程间通信的端点。在网络编程中,套接字可以被看作是不同计算机进程间通信的一个虚拟端点,允许数据通过计算机网络进行传输。
以下是套接字的定义:
套接字:在计算机网络中,套接字是一个软件抽象层,它代表了一个网络连接的一端。每个套接字都有唯一的标识,由一个IP地址和一个端口号组成。套接字使得应用程序可以发送或接收数据,而不需要了解底层网络协议的细节。
套接字分为以下几种类型:
流套接字(Stream Sockets):提供面向连接、可靠的数据传输服务,通常使用TCP(传输控制协议)来实现。适用于需要数据完整性和顺序保证的应用,如Web浏览器和电子邮件服务器。
数据报套接字(Datagram Sockets):提供无连接的数据传输服务,通常使用UDP(用户数据报协议)来实现。适用于不需要可靠传输的应用,如视频会议或在线游戏,它们可以容忍一定的数据丢失。
原始套接字(Raw Sockets):允许直接发送和接收IP协议数据包,通常用于特殊用途,如网络诊断工具或实现新的协议。

套接字的类型:
流套接字(SOCK_STREAM):提供可靠的、面向连接的服务,通常基于TCP协议。
数据报套接字(SOCK_DGRAM):提供不可靠的、无连接的服务,通常基于UDP协议。
原始套接字(SOCK_RAW):允许直接访问网络层协议,如IP或ICMP。
套接字的地址家族:
AF_INET:用于IPv4网络协议。
AF_INET6:用于IPv6网络协议。
AF_UNIX:用于Unix域套接字,用于同一主机上的进程间通信。
求同存异

可以看到,调用接口的时候必须强转成const struct sockaddr*的结构,但是不同协议簇使用的套接字是不同的,那怎么做到统一呢?

他们前16位是一样的大小,可以确定协议簇的类型,只需要强转之后取前16字节,就可以获得不同的结构。
socket 常见API
// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)
int socket(int domain, int type, int protocol);
// 绑定端口号 (TCP/UDP, 服务器)
int bind(int socket, const struct sockaddr *address,socklen_t address_len);
// 开始监听socket (TCP, 服务器)
int listen(int socket, int backlog);
// 接收请求 (TCP, 服务器)
int accept(int socket, struct sockaddr* address,socklen_t* address_len);
// 建立连接 (TCP, 客户端)
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen); sockaddr结构
UDP套接字编程
服务端
#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 <functional>
#include "Log.hpp"using namespace std;using func_t = std::function<std::string(const std::string&)>; //using xxx = 类型,是C++风格的typede
//typedef std::function<std::string(const std::string&)> func_t;Log lg;enum{SOCKET_ERR=1,BIND_ERR
};uint16_t defaultport = 8080; //端口号是一个16位无符号整数
uint32_t defaultip = INADDR_ANY; //ip地址是一个32位无符号整数 #define INADDR_ANY ((in_addr_t) 0x00000000)
const int sz = 1024;class UdpServer
{
public:UdpServer(uint16_t port = defaultport, string ip = to_string(defaultip)) //运行的时候,只需要知道端口号和ip即可: _sockfd(0), _ip(ip), _port(port), _isrunning(false){bzero(&_local, sizeof(_local));_local.sin_family = AF_INET; //网络层协议族为IPv4_local.sin_addr.s_addr = inet_addr(_ip.c_str()); //将ip字符串转换为网络字节序的32位整数_local.sin_port = htons(_port); //将端口号转换为网络字节序的16位整数/* local.sin_family = AF_INET;local.sin_port = htons(port_); //需要保证我的端口号是网络字节序列,因为该端口号是要给对方发送的local.sin_addr.s_addr = inet_addr(ip_.c_str()); //1. string -> uint32_t 2. uint32_t必须是网络序列的 // ??// local.sin_addr.s_addr = htonl(INADDR_ANY);/*单网络接口:如果你的服务器只有一个网络接口,设置 INADDR_ANY 意味着无论客户端通过哪个IP地址连接到这个服务器,服务端都会接受连接。多网络接口:如果你的服务器有多个网络接口,每个接口有不同的IP地址,设置 INADDR_ANY 则意味着无论客户端连接到哪个IP地址,服务端都会接受连接。例如,服务器可能有一个IP地址用于内部网络,另一个IP地址用于外部网络。多IP地址:如果服务器的一个网络接口配置了多个IP地址(比如通过虚拟接口或别名),设置 INADDR_ANY 允许服务端在这些所有IP地址上接受连接。也就是说,如果这个服务器存在多个ip,那么客户端与服务器通信时,可以接入本服务器的任意一个ip*///将peer暂时初始化,后续会获得peer的地址信息bzero(&_peer, sizeof(_peer));_peer.sin_family = AF_INET;_peer.sin_addr.s_addr = INADDR_ANY;_peer.sin_port = htons(0);}~UdpServer(){if (_sockfd) close(_sockfd);}public:void Init(){//1.创建UDP套接字_sockfd = socket(AF_INET,SOCK_DGRAM, 0); //int socket(int domain, int type, int protocol);if (_sockfd < 0){lg(Fatal, "socket create error, sockfd: %d", _sockfd);exit(SOCKET_ERR);}lg(Info, "socket create success, sockfd: %d", _sockfd);//绑定端口号和ip地址if (bind(_sockfd, (const struct sockaddr*)&_local, sizeof(_local)) < 0){lg(Fatal, "bind error, sockfd: %d", _sockfd);exit(BIND_ERR);}lg(Info, "bind success, sockfd: %d, ip: %s, port: %d", _sockfd, _ip.c_str(), _port);}//对代码进行分层void Run(func_t func) //这个地方需要传入一个函数指针{_isrunning = true;char buffer[sz] = {0};while (_isrunning){socklen_t len = sizeof(_peer);cout << "recv not over" << endl;ssize_t n = recvfrom(_sockfd, buffer, sz, 0, (struct sockaddr*)&_peer, &len);if (n < 0){lg(Warning, "recvfrom error, errno: %d, err string: %s", errno, strerror(errno));continue; //出错了,继续接收下一个数据包}cout << "recv over " <<endl;buffer[n] = 0;string data = buffer;string echo = func(data);sendto(_sockfd, echo.c_str(), echo.size(), 0, (const struct sockaddr*)&_peer, len);}}private:int _sockfd; //套接字描述符,一切皆文件string _ip; //我们使用的ip一般是字符串样式uint16_t _port;bool _isrunning;struct sockaddr_in _local; struct sockaddr_in _peer;
};
#include "UdpServer.hpp"
#include <memory>
#include <cstdio>using namespace std;void Usage(std::string proc)
{std::cout << "\n\rUsage: " << proc << " port[1024+]\n" << std::endl;
}string ExcuteCommand(const string& cmd)
{FILE *fp = popen(cmd.c_str(), "r");if(nullptr == fp){perror("popen");return "error";}std::string result;char buffer[4096];while(true){char *ok = fgets(buffer, sizeof(buffer), fp);if(ok == nullptr) break;result += buffer;}pclose(fp);return result;
}std::string Handler(const std::string &str)
{std::string res = "Server get a message: ";res += str;std::cout << res << std::endl;return res;
}// ./udpserver port
int main(int argc, const char* argv[])
{if(argc != 2){Usage(argv[0]);exit(0);}uint16_t port = stoi(argv[1]);unique_ptr<UdpServer> svr = make_unique<UdpServer>(port);svr->Init();svr->Run(Handler);return 0;
} 需要注意的是

1.在对sockaddr_in成员进行初始化时,需要满足网络通讯的要求:1.端口号为网络字节序 2.ip地址从字符串风格编程点分式
2.recvfrom和sendto面向的是udp通信方式,传参的时候需要将sockaddr_in结构进行强转。
3.核心为:1.创建套接字 2.绑定端口号 3.接受发送
创建套接字:

![]()
绑定端口ip时(sockaddr_in)初始化时,端口号一般ip采用通用ip。
单网络接口:如果你的服务器只有一个网络接口,设置 INADDR_ANY 意味着无论客户端通过哪个IP地址连接到这个服务器,服务端都会接受连接。
多网络接口:如果你的服务器有多个网络接口,每个接口有不同的IP地址,设置 INADDR_ANY 则意味着无论客户端连接到哪个IP地址,服务端都会接受连接。
例如,服务器可能有一个IP地址用于内部网络,另一个IP地址用于外部网络。
多IP地址:如果服务器的一个网络接口配置了多个IP地址(比如通过虚拟接口或别名),设置 INADDR_ANY 允许服务端在这些所有IP地址上接受连接。
也就是说,如果这个服务器存在多个ip,那么客户端与服务器通信时,可以接入本服务器的任意一个ip。
在计算机网络中,存在一些端口号范围被操作系统保留用于特定的服务或进程。通常,这些端口号被称为“知名端口”(Well-known ports),它们的范围是从0到1023。
端口是一个16位的数字,可供选择。
4.用socket接口返回的套接字本质是一个文件描述符,不用的时候应该关掉sockfd。
5.popen接口

参数1:传入需要执行的命令
作用:
在内部自动fork,让父子进程建立管道,让子进程执行命令,将子进程的执行结果通过管道返回给调用方。
调用方想得到command的执行结果,可以用FILE*文件指针的方式读取
参数二:执行结果的打开方式(把这个命令当成一个文件)

客户端
#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 serverportint main(int argc, const char *argv[])
{if (argc != 3){Usage(argv[0]);exit(0);}string ip = argv[1];uint16_t port = (uint16_t)stoi(argv[2]);struct sockaddr_in serveraddr; serveraddr.sin_family = AF_INET;serveraddr.sin_addr.s_addr = inet_addr(ip.c_str());serveraddr.sin_port = htons(port);int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0){cout << "create socket error" << endl;return -1;}// client 要bind吗?要!只不过不需要用户显示的bind!一般有OS自由随机选择!// 一个端口号只能被一个进程bind,对server是如此,对于client,也是如此!// 其实client的port是多少,其实不重要,只要能保证主机上的唯一性就可以!// 系统什么时候给我bind呢?首次发送数据的时候string msg;char buffer[1024];while (1){cout << "Please Enter@ ";getline(cin ,msg);sendto(sockfd, msg.c_str(), msg.size(), 0, (const struct sockaddr*)&serveraddr, sizeof(serveraddr));cout << "sendto over" << endl;struct sockaddr_in tmp;socklen_t len = sizeof(tmp);ssize_t n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&tmp, &len); //udp的数据报(数据传输模式)类型的数据需要用recvfrom读取,tcp的字节流可以用read读取if(n > 0){buffer[n] = 0;cout << buffer << endl;}}close(sockfd); return 0;
} 客户端不需要手动绑定端口号,只需要OS去绑定即可。
客户端需要对服务端的sockaddr_in结构合理的初始化,才能接收和发送到正确的Server。
TCP与UDP传输的区别
字节流(Byte Stream)和数据报(Datagram)是网络通信中两种不同的传输方式,它们在数据传输的可靠性、传输方式和用途上有所区别:
可靠性:
字节流:通常指的是面向连接的传输方式,如TCP(传输控制协议)。它提供了可靠的数据传输,确保数据按照发送顺序到达,且不会丢失或重复。
数据报:通常指的是无连接的传输方式,如UDP(用户数据报协议)。它不保证数据的可靠传输,数据包可能会丢失、重复或到达顺序错乱。
传输方式:
字节流:在字节流传输中,数据像水流一样连续传输。发送方和接收方之间存在一个持续的连接,数据按照顺序到达。
数据报:数据报传输将数据分割成小的、独立的数据包进行发送。每个数据包携带目的地址信息,但不保证按照顺序到达,也不保证所有数据包都能到达。
用途:
字节流:适用于需要高可靠性的应用,如网页浏览、文件传输、电子邮件等,这些应用需要确保数据的完整性和顺序。
数据报:适用于对实时性要求高,但可以容忍一定丢包率的场景,如视频会议、在线游戏等。这些应用更关注数据的快速传输而不是完整性。
头部开销:
字节流:由于需要维护连接状态,通常头部开销较大,因为TCP头部包含了序列号、确认号、窗口大小等信息。
数据报:UDP头部相对简单,开销较小,只包含少量的控制信息。
速度:
字节流:由于其可靠性机制,如重传机制,可能会影响传输速度。
数据报:因为没有复杂的可靠性保证机制,通常传输速度较快。
在选择字节流还是数据报时,需要根据应用的具体需求来决定。如果数据完整性和顺序至关重要,应该选择字节流;如果实时性更重要,能够容忍一定的数据丢失,那么数据报可能是更好的选择。
telnet不能链接udp服务,因为telnet底层采用的是tcp的协议。
linux相关的指令操作
netstat,可以查看本地的服务器

telnet 127.0.0.1
本地环回连接服务器,常用于测试服务器是否存在BUG。
ip地址转化函数
相关文章:
UDP网络编程套接
目录 本文核心 预备知识 1.端口号 认识TCP协议 认识UDP协议 网络字节序 socket编程接口 sockaddr结构 UDP套接字编程 服务端 客户端 TCP与UDP传输的区别 可靠性: 传输方式: 用途: 头部开销: 速度: li…...
期权VIX指数构建与择时应用
芝加哥期权交易 所CBOE的波动率指数VIX 是反映 S&P 500 指数未来 30 天预测期波动率的指标,由于预期波动率多用于表征市场情绪,因此 VIX 也被称为“ 恐慌指数”。 VIX指数计算 VIX 反映了市场情绪和投资者的风险偏好, 对于欧美市场而言…...
QT笔记- QClipboard剪切板对QByteArray数据的复制与粘贴
复制 // 存储在剪切板 QByteArray data; QClipboard * clipboard QGuiApplication::clipboard(); // 获取系统剪贴板对象 QMimeData * mimeData new QMimeData; // 注意, 剪切板会接管对象的释放 QString customMimeType "Test"; // 设置数据标识, 粘贴时将根据…...
Python使用PyMySQL操作MySQL完整指南
Python使用PyMySQL操作MySQL完整指南 1. 安装依赖 pip install pymysql2. 基础配置和数据库操作 2.1 基础配置类 import pymysql from typing import List, Dict, Optional from datetime import datetimeclass MySQLDB:def __init__(self):self.conn Noneself.cursor No…...
IAR中如何而将定义的数组放在指定的位置
在keil中可以使用下面的方法将数组定义到指定的位置 uint8_t g_usart_rx_buf[USART_REC_LEN] __attribute__ ((at(0X20001000)));但是这个方法在IAR中是用不了的,通过网上查找各种资料,发现了两种可用的方法。我这里测试的单片机是stm32f103c8t6,其他单…...
使用skywalking,grafana实现从请求跟踪、 指标收集和日志记录的完整信息记录
Skywalking是由国内开源爱好者吴晟开源并提交到Apache孵化器的开源项目, 2017年12月SkyWalking成为Apache国内首个个人孵化项目, 2019年4月17日SkyWalking从Apache基金会的孵化器毕业成为顶级项目, 目前SkyWalking支持Java、 .Net、 Node.js、…...
Ubuntu 20.04 24.04 双网卡 Bond 配置指南
前言:在现代服务器管理中,网络的稳定性和可靠性至关重要。为了提高网络的冗余性和负载能力,我们经常需要配置多个网络接口以实现链路聚合或故障转移。Ubuntu系统自17.10版本起,引入了Netplan作为新的网络配置抽象化工具࿰…...
深度学习之目标检测篇——残差网络与FPN结合
特征金字塔多尺度融合特征金字塔的网络原理 这里是基于resnet网络与Fpn做的结合,主要把resnet中的特征层利用FPN的思想一起结合,实现resnet_fpn。增强目标检测backone的有效性。代码实现如下: import torch from torch import Tensor from c…...
2024-2030全球及中国埋线针行业研究及十五五规划分析报告
2023年全球埋线针市场规模大约为0.73亿美元,预计2030年将达到1.37亿美元,2024-2030期间年复合增长率(CAGR)为9.5%。未来几年,本行业具有很大不确定性,本文的2024-2030年的预测数据是基于过去几年的历史发展…...
穷举vs暴搜vs深搜vs回溯vs剪枝专题一>子集
题目: 两个方法本质就是决策树的画法不同 方法一解析: 代码: class Solution {private List<List<Integer>> ret;//返回结果private List<Integer> path;//记录路径,注意返回现场public List<List<Int…...
MES系统工作流的单元测试方案
MES系统工作流的单元测试方案 在基于Java实现的MES系统中,若算子组成工作流并通过JSON传递数据,后端解析JSON后执行业务逻辑的流程,单元测试的核心是确保以下内容的正确性: 算子功能的正确性(每个算子单独的逻辑&…...
2.学习TypeScript 编译选项配置
自动编译 我们可以使用 tsc ...../.ts -w 命令进行ts文件的自动编译 执行后 编译会持续侦听 自动编译 这种方式只能侦听一个文件 对做项目肯定是不现实的,为了解决这个问题,我们需要添加一个tsconfig.json文件,写入一个基础对象 再有tsconfi…...
计算机网络之王道考研读书笔记-2
第 2 章 物理层 2.1 通信基础 2.1.1 基本概念 1.数据、信号与码元 通信的目的是传输信息。数据是指传送信息的实体。信号则是数据的电气或电磁表现,是数据在传输过程中的存在形式。码元是数字通信中数字信号的计量单位,这个时长内的信号称为 k 进制码…...
【BUG】记一次context canceled的报错
文章目录 案例分析gorm源码解读gin context 生命周期context什么时候cancel的什么时候context会被动cancel掉呢? 野生协程如何处理 案例分析 报错信息 {"L":"ERROR","T":"2024-12-17T11:11:33.0050800","file"…...
[SWPUCTF 2022 新生赛]善哉善哉
右击查看属性 然后放在010查看一下 摩斯密码解码 用佛曰解码 用md5加密看一下 最后一步md5,没有说明编码,尝试utf8和gbk ss4 施主,此次前来,不知有何贵干? import hashlib print(hashlib.md5(ss4.encode(utf8)).hexdigest())f…...
《PCI密码卡技术规范》题目
单选1 在《PCI密码卡技术规范》中,下列哪项不属于PCI密码卡的功能()。 A.密码运算功能 B.密钥管理功能 C.物理随机数产生功能 D.随主计算机可信检测功能 正确答案:D. <font style"color:#DF2A3F;">解析&…...
城市大屏设计素材宝库:助力设计师高效创作
城市大屏设计工作要求设计师在有限的时间内打造出令人惊叹的视觉效果,而拥有一套必备的素材集无疑是如虎添翼。这些素材犹如设计师的得力助手,无论是构建整体布局的设计模板,还是点缀细节的图标图形,都能在关键时刻发挥重要作用&a…...
HCIA-Access V2.5_5_1PON系统概述_PON网络概述
PON网络设备有很多各类,可应用于不同的业务场景,从而实现不同的业务,本章介绍PON系统应用组成,分析PON系统的硬件结构和模块功能,描述PON系统的应用场景,帮助你对接入网中设备形态有更深刻的印象。 你可以…...
群落生态学研究进展】Hmsc包开展单物种和多物种分析的技术细节及Hmsc包的实际应用
联合物种分布模型(Joint Species Distribution Modelling,JSDM)在生态学领域,特别是群落生态学中发展最为迅速,它在分析和解读群落生态数据的革命性和独特视角使其受到广大国内外学者的关注。在学界不同研究团队研发出…...
一个开源的自托管虚拟浏览器项目,支持在安全、私密的环境中使用浏览器
大家好,今天给大家分享一个开源的自托管虚拟浏览器项目Neko,旨在利用 WebRTC 技术在 Docker 容器中运行虚拟浏览器,为用户提供安全、私密且多功能的浏览体验。 项目介绍 Neko利用 WebRTC 技术在 Docker 容器中运行虚拟浏览器,提供…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...
网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
OD 算法题 B卷【正整数到Excel编号之间的转换】
文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的:a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...
