socket套接字编程之UDP协议封装

2023-05-16

1.UDP 协议特点:
①传输层协议
②无连接
③不可靠传输
④面向数据报

2.封装之前先将清楚几个要点:

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

#include <arpa/inet.h>
uint16_t htons(uint16_t hostshort);  //16位主机-->网络
uint16_t ntohs(uint16_t netshort);   //16位网络-->主机
uint32_t htonl(uint32_t hostlong);   //32位主机-->网络
uint32_t ntohl(uint32_t netlong);    //32位网络-->主机

2.2 sockaddr结构
socket API是一层抽象的网络编程接口,适用于各种底层网络协议,如IPv4、IPv6,以及后面要讲的UNIX Domain Socket. 然而, 各种网络协议的地址格式并不相同
在这里插入图片描述
①IPv4和IPv6的地址格式定义在netinet/in.h中,IPv4地址用sockaddr_in结构体表示,包括16位地址类型, 16位端口号和32位IP地址.
②IPv4、IPv6地址类型分别定义为常数AF_INET、AF_INET6. 这样,只要取得某种sockaddr结构体的首地址,不需要知道具体是哪种类型的sockaddr结构体,就可以根据地址类型字段确定结构体中的内容.
③socket API可以都用struct sockaddr *类型表示, 在使用的时候需要强制转化成sockaddr_in; 这样的好处是程序的通用性, 可以接收IPv4, IPv6, 以及UNIX Domain Socket各种类型的sockaddr结构体指针做为参数;

3.udp封装
3.1 通用接口(udpser.hpp)

#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <unistd.h>
#include <iostream>
#include <cstdio>

class UdpSvr
{
public:
  UdpSvr()
  {
    _socket = -1;
  }
  ~UdpSvr(){}

  //创建套接字
  bool CreateSocket()
  {
    _socket = socket(AF_INET, SOCK_DGRAM, 17);
    if (_socket < 0) {
      perror("socket");
      return false;
    }
    return true;
  }
  
  //绑定地址信息
  bool Bind(std::string& ip, uint16_t port)
  {
    //端口 + ip
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port); //两个字节,涉及大小端 
    addr.sin_addr.s_addr = inet_addr(ip.c_str());
    int ret = bind(_socket, (struct sockaddr*)&addr, sizeof(addr));
    if (ret < 0) {
      perror("bind");
      return false;
    }
    return true;
  }

  //发送数据
  bool Send(std::string& buf, sockaddr_in* dest_addr)
  {
    ssize_t sendSize = sendto(_socket, buf.c_str(), buf.size(), 0, (struct sockaddr*)dest_addr, sizeof(struct sockaddr_in));
    if (sendSize < 0) {
      perror("sendto");
      return false;
    }
    return true;
  }

  //接收数据
  bool Recv(struct sockaddr_in* src_addr, std::string& buf)
  {
    char tmp[1024] = {0};
    socklen_t socklen = sizeof(struct sockaddr_in);
    ssize_t ret = recvfrom(_socket, tmp, sizeof(tmp) - 1, 0, (struct sockaddr*)src_addr, &socklen);
    if (ret < 0) {
      perror("Recv");
      return false;
    }
    buf.assign(tmp, ret);
    return true;
  }

  //关闭
  void Close()
  {
    close(_socket);
    _socket = -1;
  }

private:
  int _socket;
};

udp服务器:

#include "udpser.hpp"



//ip port
//命令行参数的方式获取
//./svr ip port

int main(int argc, char* argv[])
{
  if (argc != 3)
  {
    printf("./svr [ip] [port]\n");
  }
  std::string ip = argv[1];
  uint16_t port = atoi(argv[2]);

  UdpSvr us;
  if (!us.CreateSocket()) {
    return 0;
  }

  if (!us.Bind(ip, port)) {
    return 0;
  }

  std::string buf;
  struct sockaddr_in addr;
  while (1) {
    us.Recv(&addr, buf);
    printf("client say: [%s]\n", buf.c_str());
    printf("server say: ");
    fflush(stdout);

    std::cin >> buf;
    //发送数据给客户端
    us.Send(buf, &addr);
  }
  us.Close();
  return 0;
}

udp客户端

#include "udpser.hpp"



int main(int argc, char* argv[])
{
  if (argc != 3)
  {
    printf("./cli [ip] [port]\n");
  }

  //服务端
  std::string ip = argv[1];
  uint16_t port = atoi(argv[2]);

  UdpSvr us;
  if (!us.CreateSocket()) {
    return 0;
  }


  std::string buf;
  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(port);
  addr.sin_addr.s_addr = inet_addr(ip.c_str());

  while (1) {
    printf("client say: ");
    std::cin >> buf;
    //发送数据给服务端
    us.Send(buf, &addr);

    fflush(stdout);
    us.Recv(&addr, buf);
    printf("server say: [%s]\n", buf.c_str());
  }

  us.Close();
  return 0;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

socket套接字编程之UDP协议封装 的相关文章

  • 游戏思考04:网络游戏同步算法产生原因和相关介绍:跟随(插值)、预测、延迟补偿,三种算法(未完待续02/07)

    文章目录 一 网络同步的典型场景二 简单粗暴的数据同步为何行不通 xff1f xff08 帧同步的难题 xff09 1 xff09 网络同步的流程2 xff09 网络延迟和抖动的直观解释3 xff09 产生卡顿 瞬移的原因分析4 xff09
  • 51单片机定时器实现流水灯实验

    实验内容 xff1a 利用AT89C51的定时器0 方式1实现流水灯效果 xff0c 并用仿真验证 定时器0方式1的工作方式 xff1a 定时器的工作方式选择由寄存器TMOD控制 方式选择通过M0和M1控制 xff0c 方式1为16位定时器
  • 51单片机七段数码管显示时钟无按键控制—①—74HC595版

    参考链接 xff1a 51单片机七段数码管显示时钟加按键控制 74HC595版 51单片机七段数码管显示时钟加按键控制 74HC595版 文章目录 一 实验内容 xff1a 二 实验分析 xff1a 三 仿真图 xff1a 四 源代码 xf
  • 51单片机lcd1602显示时间日期

    实验内容 xff1a 使用51单片机控制LCD1602液晶显示屏显示 时间 日期 星期 温度 信息 xff0c 并可通过按键设置值 仿真效果展示 xff1a proteus仿真图 xff1a 硬件测试图 xff1a 说明 xff1a 硬件测
  • 51单片机实现普通时钟

    一 实验内容 xff1a 1 打开单片机 xff0c 数码管显示当前时间0 0 0 xff0c 时 分 秒 xff08 时间为24小时制 xff09 2 按键1 xff1a 按下一次进入秒的修改 xff0c 按下两次修改分钟 xff0c 按
  • No suitable kits found.——QT创建项目错误

    才开始学QT就遇到一个问题 xff0c 无法创建项目 xff0c 在 Kits 这一步提示 No suitable kits found 我的错误原因 xff1a 因为以前装过MinGw环境 xff0c 而且环境里还包含着中文 xff0c
  • Keil5高亮显示相同变量加上护眼配色方案

    先上效果图 xff1a 我们知道 xff0c 之前版本的Keil是不会对相同代码进行高亮显示的 xff0c 不过现在最新版的Keil已经支持对其高亮显示了 xff0c 只不过其配色还是和原来一样有些差强人意 初始效果如下 xff1a 实现上
  • 螺旋队列公式解释

    以1为坐标零点 xff0c 向右为X正 xff0c 向下为Y正 xff0c 任意输入一坐标 xff08 x y xff0c r 61 max x y 为当前所在层数 xff0c 得到下面公式 上边 xff1a top 61 max r 43
  • Bilibili缓存视频在电脑端直接打开方式

    哔哩哔哩移动端缓存的视频和音频分开了 xff0c 使用PotPlayer播放器可以在播放视频的时候加载音频 xff0c 从而不用合并两个文件 具体操作 xff1a 使用PotPlayer播放器打开video m4s文件 打开后点鼠标右键 x
  • C语言数组、结构体、结构体数组作为函数参数

    数组作为函数参数 如果想把一个数组名参数传递给函数 xff0c 正确的函数形参应该是怎样的 xff1f 它是应该声明为一个指针还是一个数组 xff1f 调用函数时实际传递的是一个指针 xff0c 所以函数的形参实际上是一个指针 xff0c
  • 有道词典离线数据包位置

    软件版本 xff1a 9 1 0 位置 xff1a C Users 用户名 AppData Local Yodao DeskDict nmt model 将离线包放入nmt model文件夹后重新启动有道词典即可断网使用长句翻译 汉英互译离
  • 改变Keil5所有窗口的背景颜色

    在网上找了很多都没有找到如何更改Keil5左侧和下侧的背景颜色 xff0c 后来根据一些提示找到了改背景的方法 xff0c 在此分享给有需要的人 首先 xff0c 更换中间那块的背景颜色相信大家都会 xff0c 不过我还是写一下 xff0c
  • ros入门(题尾一键安装)

    运行ros 96 提示 xff1a 因为手头有英伟达树莓派跟激光雷达 xff0c 也有ros小车 直接上现成的 xff0c 但是会卡 而且不好用 xff0c 所以建议自己安装一个 链接 xff1a https pan baidu com s
  • git 基础

    git可以实现分布式的版本管理 xff0c 合作开发工具 github和gitee是代码托管平台 查看配置信息 xff1a git config list 1 我们可以通过下面两条命令配置名字和邮箱 xff0c 使代码提交有迹可循 配置名字
  • idf.py基本使用

    1 idf py set target lt target gt 设置构建项目的目标 xff08 芯片 xff09 2 idf py menuconfig 运行menuconfig工具配置项目 3 idf py build 构建在当前目录下
  • rviz更改机器人位置,不考虑gazebo环境。

    文章目录 问题描述解决方案 问题描述 在RVIZ中想要去更改机器人模型位置 xff0c 但不想考虑gazebo的各种因素 xff0c 只想通过别人给的数据流去实时更改机器人在rviz中的位置 解决方案 首先 xff0c 先将原理弄清楚 在R
  • STM32+RTC实现时钟无法设置时间以及掉电时间清零的问题

    最近在实现一个万年历的功能 xff0c 其中遇到了无法设置时间以及掉电时间清零的问题 h文件代码如下 xff1a span class token macro property span class token directive keyw
  • contains an incorrect path解决方法

    在移植UCOS 时出现如下报警 在确认头文件路径添加无误的情况下 xff0c 发现是因为文件名的UCOS 这个3不应用罗马数字 xff0c 用字母I代替 xff0c 改为UCOSIII并重新添加文件后错误消失
  • 理论 - 半波偶极子天线原理与计算

    概述 半波偶极子天线是一种结构简单的基本线天线 xff0c 也是一种经典的 迄今为止使用最广泛的天线之一 半波偶极子天线由两根直径和长度都相等的直导线组成 xff0c 每根导线的长度为1 4个工作波长 导线的直径远小于工作波长 xff0c
  • HFSS - 半波偶极子天线的设计与仿真

    一 理论计算 原理及理论计算部分可以看我上一篇文章理论 半波偶极子天线原理与计算 二 模型创建 1 模型概图如下 2 变量参数 变量意义变量名变量值 单位 mm 工作波长wavelength100天线总长度length0 48 x wave

随机推荐

  • STM32关于驱动段码屏显示

    本篇文章主要记录一下我在工作中用STM32单片机驱动段码屏显示内容 xff0c 不讲解具体的驱动原理 xff0c 只是单纯记录如何编写驱动屏幕图标显示的代码 xff0c 以便我日后查看 单片机 xff1a STM32L152RCT6A ID
  • HFSS - 同轴馈电矩形微带天线设计与仿真

    一 设计指标 中心频率 xff1a 2 45GHz介质板相对介电常数 xff1a 4 4介质板厚度 xff1a 1 6mm馈电方式 xff1a 50 Omega 同轴线馈电 二 同轴馈电微带天线设计 同轴线馈电的矩形微带天线结构如下图所示
  • HFSS - 圆极化矩形微带天线设计与仿真

    xff08 这个仿真了好久啊啊啊啊啊 xff0c 搞得这么晚 xff0c 哭辽 xff09 一 设计指标 设计一个右旋圆极化GPS天线 中心频率 xff1a 1 575GHz轴比 xff1a 中心频率处圆极化波小于2dB馈电方式 xff1a
  • HFSS - 倒F天线的设计与仿真

    一 倒F天线概述 倒F天线是单极子天线的一种变形结构 xff0c 其衍变发展的过程可以看成是从1 4波长单极子天线到倒L天线再到倒F天线的过程 xff0c 如下图所示 首先 xff0c 将单极子天线进行90 弯曲 xff0c 就能得到倒L天
  • 理论 - 平面倒F天线(PIFA)

    一 概述 PIFA Planar Inverted F shaped Antenna 天线即平面倒F形天线 xff0c 因为整个天线的形状像个倒写的英文字母F而得名 多年来 xff0c 多数手机天线都一直沿用这种传统的PIFA天线设计方案
  • HFSS - GSM 900 单频PIFA天线的设计与仿真

    一 设计指标 中心频率 xff1a 920MHz回波损耗带宽 xff1a 大于80MHz 各个参数变量如下表 变量意义变量名变量初始值 xff08 单位 xff1a mm xff09 天线高度H10辐射金属片长度L155辐射金属片宽度W13
  • HFSS - GSM 900 和 DCS 1800 双频PIFA天线的设计与仿真

    一 概述 PIFA天线可以采用在辐射金属片上开槽的技术来实现双频和多频段工作 采用如下图所示的U形开槽方案来实现PIFA天线在GSM 900和DCS 1800 两个频段上的工作 其中 xff0c 在GSM 900频段 xff0c 信号上行频
  • HFSS - 矩形口径喇叭天线的设计与仿真

    一 理论 喇叭天线是一种应用广 泛的微波天线 xff0c 其优点是结构简单 xff0c 频带宽 xff0c 功率容量大 xff0c 调整与使用方便 合理地选择喇叭尺寸 xff0c 可以获得良好的辐射特性 相当尖锐的主瓣 较小副瓣和较高的增益
  • 【record】1、FS-I6设置与对码

    官方说明文档 先贴一张官方的说明文档 xff1b 注意的点 xff1a 遥控器设置中 xff0c 按住CANCEL保存 xff1b 遥控器设置 xff08 1 xff09 恢复出厂设置 这里我对FS i6直接恢复出厂设置 xff0c 当然可
  • keil无法观察局部变量

    keil观察局部变量的时候 xff0c 发现总是显示not in scope xff0c 是优化级别过高 xff0c 降低优化级别即可
  • rplidar连接计算机显示process has died.....解决方法

    检测是否打开roscore可能是串口未赋予权限 xff0c 解决方法 xff1a sudo chmod 777 dev ttyUSB0
  • ST-LINK/V2:cannot reset target shutting down debug session

    使用 ST LINK V2 为 STM32 下载程序时 xff0c 总是不成功 xff0c 并弹出如下对话框 xff1a 解决方法 xff1a 打开 MDK 的安装目录下的 STLink xff0c 如下是我的路径 xff1a D mdk5
  • C++声明与定义以及初始化,头文件的书写规范

    初始化 初始化 xff1a 当一个对象被创建的同时获得了特定的值 1 初始化不是赋值 xff0c 初始化的含义是创建变量时赋予其一个初始值 xff0c 而赋值的含义是把对象的当前值擦除 xff0c 而以一个新值代替 xff1b 2 默认初始
  • 【C++】Cmake使用教程(看这一篇就够了)

    文章目录 引言一 环境搭建二 简单入门2 1 项目结构2 2 示例源码2 3 运行查看 三 编译多个源文件3 1 在同一个目录下有多个源文件3 1 1 简单版本3 1 1 1 项目结构3 1 1 2 示例代码3 1 1 3 运行查看 3 1
  • 编码

    UTF 8 UTF 8以字节为单位对Unicode进行编码 从Unicode到UTF 8的编码方式如下 xff1a Unicode编码 十六进制 UTF 8 字节流 二进制 000000 00007F0xxxxxxx000080 0007F
  • tensorflow-gpu1.14 + Win10 + CUDA10.0 + CUDNN7.5.0 + Python3.6 + VS2015安装

    最近学习深度学习 xff0c 在配置环境中的过程中遇到很多问题 xff0c 在这进行总结 xff0c 希望对大家有帮助 一 整个软件安装配置过程 xff0c 很多博客写的很详细 xff0c 附上链接 xff1b https blog csd
  • VS2015下配置海康威视SDK

    1网络摄像头可以在官网下载到SDK开发包 xff0c 进入海康威视官网 xff0c 选择何时的版本 xff0c 点击下载 https www hikvision com cn download 61 html 下载完成进行解压 解压完成 x
  • 如何提升串口响应速度

    最近负责编写公司的工厂模式指令集 xff0c 碰到了一些代码之外的问题 xff0c 困扰了我很久 因为综测那边对串口响应速度的要求很高 xff0c 要求从上位机下发指令开始到上位机接收到完整回复 xff0c 整个过程的响应速度要达到几十个m
  • rv1126 SDK简单编译

    rv1126 SDK简单编译 在工程的根目录下执行命令 source envsetup sh 会出现很多选项 xff0c 选择 rockchip rv1126 rv1109 spi nand 这个选项 xff0c 输入93 我的FLASH是
  • socket套接字编程之UDP协议封装

    1 UDP 协议特点 xff1a 传输层协议 无连接 不可靠传输 面向数据报 2 封装之前先将清楚几个要点 xff1a 2 1网络字节序 xff1a 注意设备的大小端 发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出 接收主机把