网络套接字补充——UDP网络编程
五、UDP网络编程
1.对于服务器使用智能指针维护生命周期;2.创建UDP套接字;3.绑定端口号,包括设置服务器端口号和IP地址,端口号一般是2字节使用uint16_t,而IP地址用户习惯使用点分十进制格式所以传入的是string类型,同时要保证网络字节序列;4.执行run;
5.1使用接口
5.1.1创建套接字
int socket(int domain, int type, int protocol);
//第一个参数为域/协议家族AF_UNIX, AF_LOCAL表示域间套接字,AF_INET ,AF_INET6表示网络套接字,AF_PACKET表示原始套接字,除了AF开头也可以PF开头;
//第二个参数表示socket的类型SOCK_STREAM表示流式套接字,SOCK_DGRAM表示数据包套接字;
//第三个参数如果只有一个协议则使用0;
//返回值是socket文件的文件描述符,打开的是网卡设备;


5.1.2进行绑定
#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
struct sockaddr {sa_family_t sa_family;char sa_data[14];
}
//第一个参数是创建好的套接字文件描述符;
//第二个参数是输入型参数,一个特定的结构需要使用其他结构进行强转;
//第三个参数特定类型的长度
//返回值成功为0失败为-1,错误码被设置;
#include <strings.h>
void bzero(void *s, size_t n);
#include <string.h>
void *memset(void *s, int c, size_t n);
//使用上述函数进行清空
typedef uint16_t in_port_t;
typedef uint32_t in_addr_t;
struct in_addr
{in_addr_t s_addr;
};
typedef unsigned short int sa_family_t;
#define __SOCKADDR_COMMON(sa_prefix) \sa_family_t sa_prefix##family
struct sockaddr_in
{__SOCKADDR_COMMON (sin_);in_port_t sin_port; /* Port number. */struct in_addr sin_addr; /* Internet address. *//* Pad to size of `struct sockaddr'. */unsigned char sin_zero[sizeof (struct sockaddr) -__SOCKADDR_COMMON_SIZE -sizeof (in_port_t) -sizeof (struct in_addr)];
};
sockaddr_in结构中,sin表示socket inet
sin_zero表示填充字段
sin_port表示端口号字段
sin_family表示使用的协议家族如AF_INET之类的
sin_addr表示的是IP地址结构
//local.sin_addr.s_addr = INADDR_ANY;//任意地址绑定
//字符串转整数接口
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int inet_aton(const char *cp, struct in_addr *inp);
in_addr_t inet_addr(const char *cp);//将字符串转32位并且是网络序列的;
//整数转字符串
char *inet_ntoa(struct in_addr in);//将整数转为字符串并且将网络字节序转为主机字节序
5.1.3数据报的读取
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
//第四个参数默认使用0以阻塞方式
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
5.1.4数据报的发送
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
5.2补充知识
1.查看网络状态
netstat -nlupa
#查看网络状态,n表示能显示成数字的就都显示成数字,l表示listen u表示udp,p表示进程,a表示所有;
2.IP问题
云服务器禁止直接绑定公网IP;配置较高的机器IP地址不唯一;只是绑定一个IP地址就会导致另一个IP地址的发往另一个IP地址的数据无法被接收;一般使用的是0,这样凡是发送给本主机的数据都要根据端口号向上交付,而不是先确定IP;即IP地址使用0表示的是任意地址绑定;
3.端口号问题
云服务器端口号默认0-1023是不允许绑定的,是系统内定的端口号,一般由固定的应用层协议使用如,http-80,https-443,MySQL-3306,普通用户直接使用的一般是1024以后的端口号,端口号的范围是0-65535,可以在这个范围内使用;
服务器需要绑定显式端口号但是客户端不需要显式绑定,操作系统会随机绑定;因为一个端口号只能被一个进程绑定,所以重复绑定同一个端口号会出错;防止出现这种冲突,就不允许用户显示绑定而是交给了操作系统,只要保证端口号的唯一性就可以,这样就不会导致不同软件的客户端出现绑定端口号冲突;一般服务器需要显示绑定端口号是因为一般是客户端先发送的请求,所以需要知道服务端的IP地址和端口号,且端口号不能发生变化必须是固定的,这样才能让客户端知道要发送的另一端进程是谁;
系统会在客户端首次发送数据的时候进行端口号的绑定;客户端可以获取多个服务器的信息所以获取信息时要包含服务端的信息;
4.本地环回地址
127.0.0.1是本地环回地址,通常来进行cs的测试;
5.3echo服务器实现
服务端
#include <sys/types.h>
#include <sys/socket.h>
#include "log.hpp"
#include <string>
#include <arpa/inet.h>
#include <cstring>
#include <cstdlib>
#include <netinet/in.h>
#include <functional>using func_t = std::function<std::string(const std::string &)>;
extern Log lg;const uint16_t defaultport = 8080;
const std::string defaultip = "0.0.0.0";
const int size = 1024;enum
{SOCKETERR = 1,BINDERR,
};class udpserver
{public:udpserver(const uint16_t &port = defaultport, const std::string &ip = defaultip) : ip_(ip), port_(port), isrunning_(false) {}~udpserver(){if (sockfd_ > 0){close(sockfd_);}}public:void init(){// 1.创建socketsockfd_ = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd_ < 0){lg(Fatal, "socket create error, sockfd: %d", sockfd_);exit(SOCKETERR);}lg(Info, "socket create success, sockfd: %d", sockfd_);// 2.bindstruct 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());local.sin_addr.s_addr = INADDR_ANY;int n = bind(sockfd_, (sockaddr *)&local, sizeof(local));if (n < 0){lg(Fatal, "bind error, errno: %d, strerror: %s", errno, strerror(errno));exit(BINDERR);}lg(Info, "bind success, errno: %d, strerror: %s", errno, strerror(errno));}void run(func_t func){isrunning_ = true;char buff[size];sockaddr_in client;socklen_t sz = sizeof(client);while (isrunning_){ssize_t n = recvfrom(sockfd_, buff, sizeof(buff) - 1, 0, (sockaddr *)&client, &sz);if (n < 0){lg(Warning, "recvfrom error, errno: %d, strerror: %s", errno, strerror(errno));continue;}buff[n] = 0;// 处理数据std::string info = buff;std::string echo_string = func(info);sendto(sockfd_, echo_string.c_str(), echo_string.size(), 0, (sockaddr *)&client, sz);}}private:int sockfd_; // 网络文件描述符std::string ip_; // IP地址,1.将字符串风格转换为uint_t类型,2.转换成网络字节序列uint16_t port_; // 端口号转换成网络字节序列bool isrunning_;
};--
void Usage(string proc)
{cout << "\n\rUsage: " << proc << " port[1024+]" << endl;
}string handler(const string &str)
{cout << str << endl;string ret = "server get a message: ";ret += str;return ret;
}int main(int argc, char *argv[])
{if (argc != 2){Usage(argv[0]);exit(0);}uint16_t port = stoi(argv[1]);unique_ptr<udpserver> svr(new udpserver(port, "127.0.0.1"));svr->init();svr->run(handler);return 0;
}
客户端
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <cstring>
#include <cstdlib>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "log.hpp"
extern Log lg;void Usage(std::string proc)
{std::cout << "\n\rUsage: " << proc << " serverip serverport\n"<< std::endl;
}
int main(int argc, char *argv[])
{if (argc != 3){Usage(argv[0]);return 0;}std::string serverip = argv[1];uint16_t serverport = std::stoi(argv[2]);int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0){std::cerr << "socket error" << std::endl;exit(1);}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());std::string message;char buff[1024];while (true){std::cout << "client say@ ";std::getline(std::cin, message);sendto(sockfd, message.c_str(), message.size(), 0, (sockaddr *)&server, sizeof(server));sockaddr_in temp;socklen_t len = sizeof(temp);ssize_t n = recvfrom(sockfd, buff, sizeof(buff) - 1, 0, (sockaddr *)&temp, &len);if (n > 0){buff[n] = 0;std::cout << buff << std::endl;}}close(sockfd);return 0;
}
5.4服务器实现执行指令
#include <stdio.h>
FILE *popen(const char *command, const char *type);
//是一个封装起来的管道和子进程执行命令的接口,会自动建立管道,让子进程执行命令并将子进程的执行结果通过管道返回给父进程;
//第一个参数是子进程要执行的命令,第二个参数是对打开文件的方式,读写;
//返回值是用来进行获取执行结果的;
int pclose(FILE *stream);
char *fgets(char *s, int size, FILE *stream);
//读取一行,当读到EOF/空时返回nullptr;
bool safecheck(const string &cmd)
{int issafe = false;vector<string> keyword;keyword.push_back("rm");keyword.push_back("mv");keyword.push_back("kill");for (auto &e : keyword){auto pos = cmd.find(e);if (pos != string::npos){return issafe;}}issafe = true;return issafe;
}string execute(const string &cmd)
{if (!safecheck(cmd)){return "unsafe";}FILE *fp = popen(cmd.c_str(), "r");if (fp == nullptr){perror("popen error: ");return "error";}char buff[4096];string ret;while (true){char *res = fgets(buff, sizeof(buff), fp);if (res == nullptr){break;}ret += buff;}cout << "get a cmd: " << cmd << endl;pclose(fp);return ret;
}
Xshell的原理就是,远端执行了一个22服务,即ssh,客户端发送指令,服务端进行执行后返回结果;

5.5Windows和Linux通信
#include<iostream>
#include<WinSock2.h>//网络套接字接口#pragma comment(lib,"ws2_32.lib")//链接静态库using namespace std;int main()
{cout << "hello client" << endl;WSADATA wsd;//创建变量int n = WSAStartup(MAKEWORD(2, 2), &wsd);//初始化//通信过程WSACleanup();//释放变量return 0;
}
#define _WINSOCK_DEPRECATED_NO_WARNINGS 1
#include<iostream>
#include<WinSock2.h>//网络套接字接口
#include<string>#pragma comment(lib,"ws2_32.lib")//链接静态库using namespace std;
const uint16_t serverport = 8080;
const string serverip = "60.205.138.126";
int main()
{cout << "hello client" << endl;WSADATA wsd;int n = WSAStartup(MAKEWORD(2, 2), &wsd);int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0){cout << "socket error" << endl;}sockaddr_in server;memset(&server, 0, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(serverport);server.sin_addr.s_addr = inet_addr(serverip.c_str());std::string message;char buff[1024];while (true){std::cout << "client say@ ";std::getline(std::cin, message);sendto(sockfd, message.c_str(), message.size(), 0, (sockaddr*)&server, sizeof(server));sockaddr_in temp;int len = sizeof(temp);int n = recvfrom(sockfd, buff, sizeof(buff) - 1, 0, (sockaddr*)&temp, &len);if (n > 0){buff[n] = 0;std::cout << buff << std::endl;}}closesocket(sockfd);WSACleanup();return 0;
}
相关文章:
网络套接字补充——UDP网络编程
五、UDP网络编程 1.对于服务器使用智能指针维护生命周期;2.创建UDP套接字;3.绑定端口号,包括设置服务器端口号和IP地址,端口号一般是2字节使用uint16_t,而IP地址用户习惯使用点分十进制格式所以传入的是string类型…...
自动化测试 —— Pytest fixture及conftest详解
前言 fixture是在测试函数运行前后,由pytest执行的外壳函数。fixture中的代码可以定制,满足多变的测试需求,包括定义传入测试中的数据集、配置测试前系统的初始状态、为批量测试提供数据源等等。fixture是pytest的精髓所在,类似u…...
Scala第十四章节(隐式转换、隐式参数以及获取列表元素平均值的案例)
章节目标 掌握隐式转换相关内容掌握隐式参数相关内容掌握获取列表元素平均值的案例 1.隐式转换和隐式参数介绍 隐式转换和隐式参数是Scala中非常有特色的功能,也是Java等其他编程语言没有的功能。我们可以很方便地利用 隐式转换来丰富现有类的功能。在后续编写Ak…...
VsCode的json文件不允许注释的解决办法
右下角找到注释点进去 输入Files: Associations搜索出此项 改为项为*.json值为jsonc保存即可 然后会发现VsCode的json文件就允许注释了...
利用图像识别进行疾病诊断
利用图像识别进行疾病诊断是人工智能和机器学习技术在医疗领域的一个重要应用。图像识别技术可以通过分析医学影像(如X光片、CT扫描、MRI、超声波图像等)来辅助医生诊断疾病。以下是图像识别在疾病诊断中的关键步骤和挑战: 数据收集与预处理…...
大数据学习-2024/3/28-excel文件的读写操作
借助第三方模块:inxlrd,xlwt pip 第三方模块包管理工具 –> winr --> cmd --> 打开操作系统 –> python --> 查看默认的解释器版本 --> exit() –> pip list --> 查看第三方模块的列表 pip36 list --> 查看3.6版本安装的第三方模块列表 –> pip[…...
k8s 如何获取加入节点命名
当k8s集群初始化成功的时候,就会出现 加入节点 的命令如下: 但是如果忘记了就需要找回这条命令了。 kubeadm join 的命令格式如下:kubeadm join --token <token> --discovery-token-ca-cert-hash sha256:<hash>--token 令牌--…...
黑群晖基于docker配置frp内网穿透
前言 我的黑群晖需要设置一下内网穿透来外地访问,虽然zerotier的p2p组网已经很不错了,但是这个毕竟有一定的局限性,比如我是ios的国区id就下载不了zerotier的app,组网不了 1.下载镜像 选择第一个镜像 2.映射文件 配置frpc.ini&a…...
多线程基础:线程通信内容补充
多线程基础:线程通信内容补充 文章目录 多线程基础:线程通信内容补充前言一、wait(), notify(), notifyAll()二、join()三、Lock 和 Condition四、并发集合和原子变量1、并发集合2、原子变量 总结 前言 前文内容中讲了线程通信的内容,但是不…...
使用Jenkins打包时执行失败,但手动执行没有问题如ERR_ELECTRON_BUILDER_CANNOT_EXECUTE
具体错误信息如: Error output: Plugin not found, cannot call UAC::_ Error in macro _UAC_MakeLL_Cmp on macroline 2 Error in macro _UAC_IsInnerInstance on macroline 1 Error in macro _If on macroline 9 Error in macro FUNCTION_INSTALL_MODE_PAGE_FUNC…...
OpenCV图像滤波、边缘检测
OpenCV图像滤波 一、引言 在数字图像处理中,滤波是一种重要的技术,用于消除图像中的噪声、改善图像质量或提取特定信息。OpenCV(开源计算机视觉库)提供了丰富的滤波函数,可以方便地对图像进行各种滤波操作。本文将介…...
前端项目在本地localhost可以调取到拍照或麦克风等设备,但是在局域网内IP+端口号访问项目时访问不到设备
前端项目在本地localhost可以调取到拍照或麦克风等设备,但是在局域网内IP端口号访问项目时访问不到设备,调取navigation.mediaDevices时本科可以获取到mediaDevices列表,局域网内ip端口访问时获取不到mediaDevices。 原因: 存在…...
flutter生成二维码并截图保存到图库
引入库:flutter_screenutil、image_gallery_saver、qr_flutter弹窗布局 import dart:async; import dart:typed_data; import package/generated/l10n.dart; import package:jade/configs/PathConfig.dart; import package:jade/utils/ImageWaterMarkUtil.dart; im…...
EasyExcel Converter实现java对象和excel单元格转换
在EasyExcel中,Converter接口用于定义如何在Java对象和Excel单元格之间进行转换。 也就是说EasyExcel可以根据数据库中的值来填充Excel中对应的文本内容。 比如数据库1,2,3可以填充到excel中:男,女,其他 使用easyExcel的之前&a…...
stamac Ethernet DTS配置
目录 Demo 配置 compatible reg interrupts & interrupt-names phy-mode phy-handle Snps,reset-gpio...
Svg Flow Editor 原生svg流程图编辑器(四)
系列文章 Svg Flow Editor 原生svg流程图编辑器(一) Svg Flow Editor 原生svg流程图编辑器(二) Svg Flow Editor 原生svg流程图编辑器(三) Svg Flow Editor 原生svg流程图编辑器(四…...
Verilog语法之assign语句学习
assign语法主要是对组合逻辑的变量进行赋值的,就是把一个变量赋值给另一个变量,被复制的变量必须是wire类型的参数。 从仿真结果可以看出,data_in变量的值赋值给了data_out,assign语法就是赋值没有任何延迟,data_in是什么值&#…...
Cocos2dx-lua ScrollView[三]高级篇
一.概述 本文缩写说明:sv ScrollView, cell代表ScrollView的一个子节点 本文介绍sv的一种封装类库,来实现快速创建sv,有如下几个优点: 1.item的位置通过参数控制,提高开发效率 2.免去了调用sv的API,提…...
后端之卡尔曼滤波
后端之卡尔曼滤波 前言 在很久之前,人们刚结束信息传递只能靠信件的时代,通信技术蓬勃发展,无线通信和有线通信走进家家户户,而著名的贝尔实验室就在这个过程做了很多影响深远的研究。为了满足不同电路和系统对信号的需求&#…...
Docker 夺命连环 15 问
目录 什么是Docker? Docker的应用场景有哪些? Docker的优点有哪些? Docker与虚拟机的区别是什么? Docker的三大核心是什么? 如何快速安装Docker? 如何修改Docker的存储位置? Docker镜像常…...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
Python实现简单音频数据压缩与解压算法
Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中,压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言,提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...
规则与人性的天平——由高考迟到事件引发的思考
当那位身着校服的考生在考场关闭1分钟后狂奔而至,他涨红的脸上写满绝望。铁门内秒针划过的弧度,成为改变人生的残酷抛物线。家长声嘶力竭的哀求与考务人员机械的"这是规定",构成当代中国教育最尖锐的隐喻。 一、刚性规则的必要性 …...
数据库——redis
一、Redis 介绍 1. 概述 Redis(Remote Dictionary Server)是一个开源的、高性能的内存键值数据库系统,具有以下核心特点: 内存存储架构:数据主要存储在内存中,提供微秒级的读写响应 多数据结构支持&…...
2025-05-08-deepseek本地化部署
title: 2025-05-08-deepseek 本地化部署 tags: 深度学习 程序开发 2025-05-08-deepseek 本地化部署 参考博客 本地部署 DeepSeek:小白也能轻松搞定! 如何给本地部署的 DeepSeek 投喂数据,让他更懂你 [实验目的]:理解系统架构与原…...
EasyRTC音视频实时通话功能在WebRTC与智能硬件整合中的应用与优势
一、WebRTC与智能硬件整合趋势 随着物联网和实时通信需求的爆发式增长,WebRTC作为开源实时通信技术,为浏览器与移动应用提供免插件的音视频通信能力,在智能硬件领域的融合应用已成必然趋势。智能硬件不再局限于单一功能,对实时…...
