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 容器中运行虚拟浏览器,提供…...

职场上,如何做好自我保护?
今天我们讨论一个话题:在职场上,如何保护好自己?废话不多说,我们直接上干货。 (一) 1.时刻准备一点零食或代餐,如果遇到长时间的会议,就补充点能量。代餐最好选流体,这…...

华为数通最新题库 H12-821 HCIP稳定过人中
以下是成绩单和考试人员 HCIP H12-831 HCIP H12-725 安全中级...

mac iterm2 使用 lrzsz
前言 mac os 终端不支持使用 rz sz 上传下载文件,本文提供解决方法。 mac 上安装 brew install lrzsz两个脚本 注意:/usr/local/bin/iterm2-send-zmodem.sh 中的 sz命令路径要和你mac 上 sz 命令路径一致。 /usr/local/bin/iterm2-recv-zmodem.sh 中…...

PostgreSql-学习06-libpq之同步命令处理
目录 一、环境 二、介绍 三、函数 1、PQsetdbLogin (1)作用 (2)声明 (3)参数介绍 (4)检测成功与否 2、PQfinish (1)作用 (2࿰…...

简单配置,全面保护:HZERO审计服务让安全触手可及
HZERO技术平台,凭借多年企业资源管理实施经验,深入理解企业痛点,为您提供了一套高效易用的审计解决方案。这套方案旨在帮助您轻松应对企业开发中的审计挑战,确保业务流程的合规性和透明度。 接下来,我将为大家详细介绍…...

HCIA-Access V2.5_4_1_1路由协议基础_IP路由表
大型网络的拓扑结构一般会比较复杂,不同的部门,或者总部和分支可能处在不同的网络中,此时就需要使用路由器来连接不同的网络,实现网络之间的数据转发。 本章将介绍路由协议的基础知识、路由表的分类、静态路由基础与配置、VLAN间…...

Spring IOC 和 AOP的学习笔记
Spring框架是java开发行业的标准 Spring全家桶 Web:Spring Web MVC/Spring MVC、Spring Web Flux 持久层:Spring Data / Spring Data JPA 、Spring Data Redis 、Spring Data MongoDB 安全校验:Spring Security 构建工程脚手架ÿ…...

二七(vue2-03)、生命周期四个阶段及八个钩子、工程化开发和脚手架、组件注册、拆分组件
1. 生命周期 1.1 生命周期四个阶段 <!-- Vue生命周期:一个Vue实例从 创建 到 销毁 的整个过程。生命周期四个阶段:① 创建 ② 挂载 ③ 更新 ④ 销毁1.创建阶段:创建响应式数据2.挂载阶段:渲染模板3.更新阶段:修改…...

[树] 最轻的天平
问题描述 天平的两边有时不一定只能挂物品,还可以继续挂着另一个天平,现在给你一些天平的情况和他们之间的连接关系,要求使得所有天平都能平衡所需物品的总重量最轻。 一个天平平衡当且仅当“左端点的重量 \times 左端点到支点的距离 …...

Linux udev介绍使用
udev udev配置文件匹配键和赋值键操作符解释示例修改udev配置U盘自动挂载Usb卸载SD卡挂载SD卡卸载 udev配置文件 /etc/udev/udev.conf 这个文件通常很短,他可能只是包含几行#开头的注释,然后有几行选项: udev_root“/dev/” udev_rules“/…...