当前位置: 首页 > news >正文

【网络】:网络套接字(UDP)

网络套接字

  • 一.网络字节序
  • 二.端口号
  • 三.socket
    • 1.常见的API
    • 2.封装UdpSocket
  • 四.地址转换函数

网络通信的本质就是进程间通信。

一.网络字节序

我们已经知道,内存中的多字节数据相对于内存地址有大端和小端之分, 磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分,网络数据流同样有大端小端之分. 那么如何定义网络数据流的地址呢?

  1. 发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出;
  2. 接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存;
  3. 因此,网络数据流的地址应这样规定:先发出的数据是低地址,后发出的数据是高地址.
  4. TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节.
  5. 不管这台主机是大端机还是小端机, 都会按照这个TCP/IP规定的网络字节序来发送/接收数据;
  6. 如果当前发送主机是小端, 就需要先将数据转成大端; 否则就忽略, 直接发送即可;

为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换。

在这里插入图片描述

这些函数名很好记,h表示host,n表示network,l表示32位长整数,s表示16位短整数。
例如htonl表示将32位的长整数从主机字节序转换为网络字节序,例如将IP地址转换后准备发送。
如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回 ; 如果主机是大端字节序,这些 函数不做转换,将参数原封不动地返回。

二.端口号

在进行网络通信中,下三层主要解决的是数据可靠的传输到远端机器,而应用层主要是来处理数据的。而应用层有很多程序,例如:微信,抖音…底层如何知道这个数据传给哪一个呢?这时就要引入端口号了。

在这里插入图片描述

端口号(port)是传输层协议的内容:

  1. 端口号是一个2字节16位的整数;
  2. 端口号用来标识一个进程, 告诉操作系统, 当前的这个数据要交给哪一个进程来处理;
  3. IP地址 + 端口号能够标识网络上的某一台主机的某一个进程;
  4. 一个端口号只能被一个进程占用

在这里插入图片描述

IP地址能表示唯一的主机,port端口号能标识该主机上唯一的进程。当两者连在一起时,我们就能准确的找到目的机器的具体接收信息的应用了。这种IP+port方式就叫做socket.

三.socket

1.常见的API

在这里插入图片描述

socket API是一层抽象的网络编程接口,适用于各种底层网络协议,如IPv4,IPv6,以及后面要讲的UNIX DomainSocket. 然而, 各种网络协议的地址格式并不相同

在这里插入图片描述

  1. IPv4和IPv6的地址格式定义在netinet/in.h中,IPv4地址用sockaddr_in结构体表示,包括16位地址类型, 16位端口号和32位IP地址.
  2. IPv4、IPv6地址类型分别定义为常数AF_INET、AF_INET6. 这样,只要取得某种sockaddr结构体的首地址,不需要知道具体是哪种类型的sockaddr结构体,就可以根据地址类型字段确定结构体中的内容.
  3. socket API可以都用struct sockaddr *类型表示, 在使用的时候需要强制转化成sockaddr_in; 这样的好处是程序的通用性, 可以接收IPv4, IPv6, 以及UNIX Domain Socket各种类型的sockaddr结构体指针做为参数;

2.封装UdpSocket

#pragma once#include<iostream>
#include<sys/types.h>
#include<sys/socket.h>
#include<strings.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>
#include "log.hpp"extern Log log;std::string defaultip="0.0.0.0";
uint16_t defaultport=8080;
const int size=1024;enum{SOCKET_ERR=1,BIND_ERR
};class UdpServer
{
public://初始化端口号,ip号UdpServer(const uint16_t &port=defaultport,const std::string &ip=defaultip): port_(port),ip_(ip){}void init(){//创建udp socketsockfd_=socket(AF_INET,SOCK_DGRAM,0);if(socket<0)//创建失败{log(Fatal,"socket create error: %d",sockfd_);exit(SOCKET_ERR);}log(Info,"create socket sucess:%d",sockfd_);//绑定端口号struct sockaddr_in local;//将该结构体内部清零bzero(&local,sizeof(local));//填充结构体local.sin_family=AF_INET;//表明自己的结构体类型local.sin_port=htons(port_);//绑定的端口号,需要保证我的端口号是网络字节序列(大端),因为要发送给对方,所以htos转换local.sin_addr.s_addr=inet_addr(ip_.c_str());//绑定的ip,1.ting->uint_32 2.必须是网络序列的//上面的全部定义在用户栈上,并没有与内核绑定//绑定内核int n=bind(sockfd_,(const struct sockaddr*)&local,sizeof(local));if(n<0)//绑定失败{log(Fatal,"bind error,error:%s",strerror(errno));exit(BIND_ERR);}log(Info,"bind sucess:%d",sockfd_);}void run(){isrunning=true;while(isrunning){char inbuffer[size];struct sockaddr_in client;//客户端结构体socklen_t len=sizeof(client);ssize_t n=recvfrom(sockfd_,inbuffer,sizeof(inbuffer)-1,0,(struct sockaddr*)&client,&len);if(n<0){log(Warning,"recvform err,err string:%s",strerror(errno));continue;}inbuffer[n]=0;//简单的数据处理std::string info=inbuffer;std::string echo_string="server echo"+info;//将数据发回sendto(sockfd_,echo_string.c_str(),echo_string.size(),0,(const sockaddr*)&client,len);}}~UdpServer(){}private:int sockfd_;//网络文件描述符uint16_t port_;//端口号std::string ip_;//ip号bool isrunning;
};

可以使用netstat -naup查看是否启动成功。

在这里插入图片描述

四.地址转换函数

本节只介绍基于IPv4的socket网络编程,sockaddr_in中的成员struct in_addr sin_addr表示32位 的IP 地址但是我们通常用点分十进制的字符串表示IP 地址,以下函数可以在字符串表示 和in_addr表示之间转换;

字符串转in_addr的函数:

在这里插入图片描述

in_addr转字符串的函数:

在这里插入图片描述

其中inet_pton和inet_ntop不仅可以转换IPv4的in_addr,还可以转换IPv6的in6_addr,因此函数接口是void*addrptr。

关于ntoa

inet_ntoa这个函数返回了一个char*, 很显然是这个函数自己在内部为我们申请了一块内存来保存ip的结果.
那么是否需要调用者手动释放呢?

在这里插入图片描述

man手册上说, inet_ntoa函数, 是把这个返回结果放到了静态存储区. 这个时候不需要我们手动进行释放.

那么问题来了, 如果我们调用多次这个函数, 会有什么样的效果呢? 参见如下代码:

在这里插入图片描述

在这里插入图片描述

因为inet_ntoa把结果放到自己内部的一个静态存储区, 这样第二次调用时的结果会覆盖掉上一次的结果.

相关文章:

【网络】:网络套接字(UDP)

网络套接字 一.网络字节序二.端口号三.socket1.常见的API2.封装UdpSocket 四.地址转换函数 网络通信的本质就是进程间通信。 一.网络字节序 我们已经知道,内存中的多字节数据相对于内存地址有大端和小端之分, 磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分,网…...

Linux编程 1/2 数据结构

数据结构: 程序 数据结构 算法 1.数据结构: 1.时间复杂度: 数据量的增长与程序运行时间增长所呈现的比例函数,则称为时间渐进复杂度函数简称时间复杂度 O(c) > O(logn)> O(n) > O(nlogn) > O(n^2) > O(n^3) > O(2^n) 2.空间复杂度: 2.类…...

【UE Niagara】实现闪电粒子效果的两种方式

目录 效果 步骤 方式一&#xff08;网格体渲染器&#xff09; &#xff08;1&#xff09;添加网格体渲染器 &#xff08;2&#xff09;修改粒子显示方向 &#xff08;3&#xff09;添加从上到下逐渐显现的效果 &#xff08;4&#xff09;粒子颜色变化 方式二&#xff0…...

js数组/对象的深拷贝与浅拷贝

文章目录 一、js中的深拷贝和浅拷贝二、浅拷贝1、Object.assign()2、利用es6扩展运算符&#xff08;...&#xff09; 二、深拷贝1、JSON 序列化和反序列化2、js原生代码实现3、使用第三方库lodash等 四、总结 一、js中的深拷贝和浅拷贝 在JS中&#xff0c;深拷贝和浅拷贝是针对…...

HCIA学习第六天:OSPF:开放式最短路径优先协议

OSPF&#xff1a;开放式最短路径优先协议 无类别链路状态IGP动态路由协议 1.距离矢量协议&#xff1a;运行距离矢量协议的路由器会周期性的泛洪自己的路由表。通过路由的交互&#xff0c;每台路由器从相邻的路由器学习到路由&#xff0c;并且加载进自己的路由表中&#xff1b…...

从四个方面来解决企业在项目管理中遇到的各类问题

案例背景&#xff1a;某建筑集团有限公司成立于1949年&#xff0c;拥有国家房屋建筑工程施工总承包一级、建筑装修装饰工程专业承包一级、市政公用工程施工总承包一级资质。是一家集建筑施工、设备安装、装饰装潢、仿古建筑、房地产开发、建材试验为一体的具有综合生产能力的建…...

使用代码取大量2*2像素图片各通道均值,存于Excel文件中。

任务是取下图RGB各个通道的均值及标签&#xff08;R, G&#xff0c;B&#xff0c;Label&#xff09;,其中标签由图片存放的文件夹标识。由于2*2像素图片较多&#xff0c;所以将结果放置于Excel表格中&#xff0c;之后使用SVM对他们进行分类。 from PIL import Image import os …...

React16源码: React中commit阶段的commitBeforeMutationLifecycles的源码实现

commitBeforeMutationLifecycles 1 &#xff09;概述 在 react commit 阶段的 commitRoot 第一个while循环中调用了 commitBeforeMutationLifeCycles现在来看下&#xff0c;里面发生了什么 2 &#xff09;源码 回到 commit 阶段的第一个循环中&#xff0c;在 commitRoot 函数…...

压制二元组的总价值

压制二元组的总价值 对于每一个 a i a_i ai​, 看它能压制它前面的多少个元素, 那么它对总价值的贡献就是: 在a数组中: a i a_i ai​压制了x个数, 贡献为: x ∗ i x*i x∗i被 a i a_i ai​所压制的所有数在 a a a中的下标和为 y y y, 贡献为 − y -y −y 树状数组来求: 为了…...

【习题】保存应用数据

判断题 1. 首选项是关系型数据库。 错误(False) 2. 应用中涉及到Student信息&#xff0c;如包含姓名&#xff0c;性别&#xff0c;年龄&#xff0c;身高等信息可以用首选项来存储。 错误(False) 3. 同一应用或进程中每个文件仅存在一个Preferences实例。 正确(True) 单选题 …...

Flask框架小程序后端分离开发学习笔记《5》简易服务器代码

Flask框架小程序后端分离开发学习笔记《5》 Flask是使用python的后端&#xff0c;由于小程序需要后端开发&#xff0c;遂学习一下后端开发。 简易服务器代码 接口解析那一块很关键&#xff0c;学后端服务器这一块&#xff0c;感觉主要就是学习相应地址的接口怎么处理。 然后…...

“计算机视觉处理设计开发工程师”专项培训(第二期)

“人工智能技术与咨询” 发布...

R语言学习case7:ggplot基础画图(核密度图)

step1: 导入ggplot2库文件 library(ggplot2)step2&#xff1a;带入自带的iris数据集 iris <- datasets::irisstep3&#xff1a;查看数据信息 dim(iris)维度为 [150,5] head(iris)查看数据前6行的信息 step4&#xff1a;画图展示 plot2 <- ggplot(iris,aes(Sepal.W…...

Ubuntu18配置Docker

1.基本过程 1.更新软件源列表 sudo apt update2.安装软件包依赖 sudo apt install apt-transport-https ca-certificates curl software-properties-common3.在系统中添加Docker的官方密钥 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - …...

Keil/MDK平台 - 结构体成员指针注意事项

文章目录 1 . 前言总结2 . 问题现象3 . 解决思路4 . 细节扩展5 . 总结 【极客技术传送门】 : https://blog.csdn.net/Engineer_LU/article/details/135149485 1 . 前言总结 有时候希望通过类定义的类型指向数据包来解析&#xff0c;恰好又想结构体内定义指针指向一段数据&…...

一款超级好用的远程控制APP,你值得拥有

在这个科技日新月异的时代&#xff0c;我们的生活被各种手机软件所包围。几乎每个人都有一个甚至多个手机&#xff0c;你是否也有遇到过需要远程操作自己某一台手机的场景呢&#xff1f;今天&#xff0c;我要向大家推荐一款神奇的手机远程操作神器&#xff0c;让你可以随时随地…...

NumPy必知必会50例 | 18. 使用 NumPy 解决线性方程组:数学问题的实用解决方案

继续我们的 NumPy 探索之旅吧&#xff0c;接下来我们将探讨使用 NumPy 解决线性方程组&#xff0c;一种实用的数学应用。 文章目录 18. 使用 NumPy 解决线性方程组&#xff1a;数学问题的实用解决方案线性方程组&#xff1a;数学世界的基石创建线性方程组 解决实际问题应用场景…...

C/C++编码问题研究

文章目录 一、Unicode字符集与U8/U16/U32编码二、编码1. 占字节数2. ASCII、GB2312、GBK、GB18030 以及 UTF8 的关系3. BOM4. UTF-8的存储实现 三、编译器字符集设置1. GCC语法Example 2. MSVC语法Example 三、wchar_t五、编码转换函数六、代码 & 实践1. UTF8与UTF16、UTF3…...

二刷代码随想录|Java版|回溯算法3|子集问题

习题 2.3 子集问题 就是组合过程收集path。就像是代码随想录里说得那样&#xff0c;组合和分割问题就是收集叶子结点&#xff0c;子集问题就是收集每一个节点。 有涉及到同层重复元素的问题。 先排序&#xff0c;后再for循环里处理相同数值跳过。 设置函数内的used。 还可以用…...

mongodb config

windows&#xff1a; 1.同级bin&#xff0c;data&#xff0c;log创建mongo.config文件 dbpathD:\Program\mongodb\data\db logpathD:\Program\mongodb\log\mongo.log logappendtrue #默认启用日志 journaltrue #过滤无用日志信息&#xff0c;调试设置为false quiettrue port2…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南

1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发&#xff0c;使用DevEco Studio作为开发工具&#xff0c;采用Java语言实现&#xff0c;包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机

这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机&#xff0c;因为在使用过程中发现 Airsim 对外部监控相机的描述模糊&#xff0c;而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置&#xff0c;最后在源码示例中找到了&#xff0c;所以感…...

MySQL 部分重点知识篇

一、数据库对象 1. 主键 定义 &#xff1a;主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 &#xff1a;确保数据的完整性&#xff0c;便于数据的查询和管理。 示例 &#xff1a;在学生信息表中&#xff0c;学号可以作为主键&#xff…...

Golang——9、反射和文件操作

反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一&#xff1a;使用Read()读取文件2.3、方式二&#xff1a;bufio读取文件2.4、方式三&#xff1a;os.ReadFile读取2.5、写…...

比较数据迁移后MySQL数据库和OceanBase数据仓库中的表

设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...