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

UDP_SOCKET编程实现

文章目录

  • socket编程接口
    • 认识`struct sockaddr`类
  • 编写一个server服务
  • Client代码
  • 查看启动结果
  • 代码修正
    • 1.获取内核分配给客户端的信息
    • 2.修正不匹配ip不能访问的问题
  • 不同机器之间的通信
    • 利用xftp将udp_client传给wsl的ubuntu机器进行演示
    • 现在模拟在windows下的udp_client代码:
  • 对方发的命令也进行执行或者是打印
  • udp tcp是支持全双工的, 所以我们可以实现一个聊天室

socket编程接口

socket常见接口API:
在这里插入图片描述

认识struct sockaddr

网络套接字编程时,socket也分很多类:
1.unix socket:域间socket->用的是同一套接口, 不过用的是同一台机器上的文件路径,类似命名管道,负责本主机内部进行通信
2.网络socket:ip+port 网络通信(也可实现本地socket)(重点)
3.原始socket(应用层直接访问数据链路层,一般用于编写一些网络工具)

设计者想实现在不同应用场景使用一套接口,struct sockaddr{};是一个通用的地址类型

在这里插入图片描述
在这里插入图片描述
由于历史原因, 当初设计的时候不支持void*的通用接口
所以使用这样的方式

编写一个server服务

实现一个服务:
封装一个udpserver
构建服务基本框架:
UdpServer.hpp

#pragma once
#include "nocopy.hpp"
#include <iostream>
//父类内不存在拷贝, 所以基类也不存在拷贝
class UdpServer : public nocopy
{
public:UdpServer(){}void Init(){}void Start(){}~UdpServer(){}
private:
};

Main.cc

	#include "UdpServer.hpp"#include <memory>int main(){   //使用std::make_unique函数初始化它std::unique_ptr<UdpServer> usvr = std::make_unique<UdpServer>();usvr->Init();usvr->Start();return 0;}

为了防止这个类服务被拷贝, 所以禁用一系列的拷贝函数
nocopy.hpp

	#pragma once#include <iostream>class nocopy{public:nocopy() = default;nocopy(const nocopy&) = delete;const nocopy& operator=(const nocopy&) = delete;//推荐禁用上面那个//nocopy& operator=(const nocopy&) = delete;~nocopy() = default;
};

socket编写:
在这里插入图片描述

返回值:
创建成功返回一个文件描述符,出错返回-1

在这里插入图片描述
在这里插入图片描述
参数3:
确认是udp还是TCP
udp这里是固定写法
创建套接字
在这里插入图片描述绑定网络信息

在这里插入图片描述

返回值: 成功为0 , 错误返回-1, 错误码被设置
参数2虽然是struct sockaddr但是我们要使用网络套接字中的struct sockaddr_in:

在这里插入图片描述

首先这个填充字段指的是:
在这里插入图片描述
in_addr类是指
在这里插入图片描述
在这里插入图片描述
是指
在这里插入图片描述
##表示拼接
将传入的参数与##后面的符号进行拼接
所以这个结构体内的宏代表的参数是sin_family

struct sockaddr_in local;
bzero(&local, sizeof(local)); // 指定的内存大小清零, 头文件是<strings.h>// 也可以使用memset
// 告诉系统绑定网络通信的信息
local.sin_family = AF_INET; // 协议家族,s表示socket的意思
// in表示inet, 使用ipconfig查看会发现inet表示IP地址,
// 这的in也表示ip地址, 与上文的创建socket的参数1不同, 这边只是绑定信息
local.sin_port = htons(_port);
local.sin_addr.s_addr = inet_addr(_ip.c_str());

//我们自己写的是一个主机序列, 要转化为网络序列htons();
//主机转网络短整型, 同样在结构体内的是类型匹配的

在这里插入图片描述
对于我们的网络IP, 同样, 我们想要1. 4字节IP 2. 转成网络序列
在这里插入图片描述

将输入的字符串IP转化为点分十进制IP,并返回
在这里插入图片描述
结构体填完, 只是在当前的用户地址空间, 但是还没有设置到内核, 需要调用bind函数在这里插入图片描述
udp服务器接发消息, 它不面向连接:
收消息:

在这里插入图片描述
在这里插入图片描述发消息
在这里插入图片描述
至此已完成, 运行查看:
在这里插入图片描述

怎么验证:

在这里插入图片描述

n:number数字
a:all 所有的
u:udp
p:process进程

在这里插入图片描述

Client代码

创建套接字
在这里插入图片描述

客户端信息输入:
在这里插入图片描述

发送信息

在这里插入图片描述

接受消息
在这里插入图片描述

查看启动结果

信息查看
在这里插入图片描述

带上-n选项
在这里插入图片描述
127.0.0.1: 本地环回地址, 通常用于进行网路cs(client server)的测试
在这里插入图片描述

cs都在一台机器, 用于测试将信息自己发给自己是否正确

带上-p选项
在这里插入图片描述

输出的信息
在这里插入图片描述
客户端的端口号和ip自动变成了
在这里插入图片描述
客户端的首次运行, 在没有发消息时, 看不到client的相关网络信息:
只有在client发送一条信息之后, 才会看到client的相关信息
说明, 客户端bind是在首次发送数据的时候, 进行由内核随机bind

代码修正

1.获取内核分配给客户端的信息

在server模块中, client首次发送的消息会被recvfrom函数接受, 那么这个函数的后两个参数就是表示这个客户端的信息
所以, 打印需要的信息
在这里插入图片描述
再次运行查看:
在这里插入图片描述

127.0.0.1: 本地环回地址, 通常用于进行网路cs(client server)的测试

cs都在一台机器, 用于测试将信息自己发给自己是否正确

为了封装性, 将客户端信息进行封装:

在这里插入图片描述

在这里插入图片描述
本地测试完成
但是我们的服务器ip绑定只能是127.0.0.1本机, 如果是实际的本地机器, 本地ip也可以, 云服务器的ip不行, 因为云服务器的IP是提供商虚拟出来的公网Ip, 不能直接进行bind
当然, 也不推荐给服务器绑定固定的IP, 使用随机ip更合适, 这样就能实现IP的动态绑定, 不然, 只能绑定的固定的ip机器进行服务器的访问

2.修正不匹配ip不能访问的问题

在这里插入图片描述

固定ip才能访问
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

对应的main.cc文件内以及udpserver.hpp文件的所有的server的ip都要去除, 这边就不再演示

不同机器之间的通信

利用xftp将udp_client传给wsl的ubuntu机器进行演示

传过去默认没有可执行 chmod +x udp_client即可
这边演示两台机器上的相互通信, 原机是虚拟机ubuntu机器

现在在windows下使用wsl创建一台ubuntu机器, 两台机器ip不同
都是虚拟出来的ip

在这里插入图片描述

现在模拟在windows下的udp_client代码:

可以看到win和linux进行了通信
只不过win的汉字编码和Linux汉字的编码方式不同, 输入过去的汉字不能正确的回显, 这边只需要修改win的终端编码方式即可,这边就不再演示

对方发的命令也进行执行或者是打印

可以使用exec*系列进行使用, 不过这边利用popen函数
做两件事:
1.创建管道
2.识别字符指令, fork创建子进程并执行
在这里插入图片描述

可以利用FILE的文件指针, 返回command的结果
type可以利用r w r+等方式来进行处理我们的这个FILE

最后使用pclose进行关闭
打开失败就返回nullptr

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

udp tcp是支持全双工的, 所以我们可以实现一个聊天室

udp+线程池实现聊天室:
在线程池中, 任务现在是一个函数方法
在这里插入图片描述

在server启动的时候
首先进行, 将远端的信息接收进buf中,同时被填充的peer结构体中包含对应机器的port和ip
然后判断就收消息成功之后, 添加用户和用户输入的信息获取, 然后进行message的处理方法Route与当前对象, 当前客户端的信息, 当前的message绑定为task, 然后将这个task添加到线程池中

在这里插入图片描述

其中:
添加用户操作为看他是否在当前的用户列表中,不在,就添加
在这里插入图片描述

收到的message消息的处理方式是
在这里插入图片描述

将给定的消息message通过套接字sock发送给所有在线用户

然后在线程池中, 进行阻塞队列式的执行访问

然后对client进行多线程修改, 一个线程专门用于收消息, 一个线程专用于发消息, 主线程用于操作这个整体流程
在这里插入图片描述
整体没变, 实现模块化的划分:
在这里插入图片描述
聊天室实现成功, 但是输出和输入会混在一起. 再次修改
在linux中, 每个 终端是在/dev/pts 目录下有存在, 直接在这边输出信息也行, 方法有很多, 这边可以使用向/dev 输出的操作, 我们使用另一种方式
在输出消息的时候, 代码部分是向cerr打印, 那么我们可以利用管道, 在终端使用重定向实现输入输出的分别实现
1.创建管道
在这里插入图片描述
2.重定向输出
server端不变
在这里插入图片描述

演示
在这里插入图片描述

现在在回回显处进行修改代码, 以便确认身份
主要是在message进行修改,
在这里插入图片描述

然后输出的时候, 直接输出就行
在这里插入图片描述

结果演示:
在这里插入图片描述

就此, udp_socket完成

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 2、electron vue3 怎么创建子窗口,并给子窗口路由传参
  • WEB攻防-JS项目Node.js框架安全识别审计验证绕过
  • 好用的工具网址
  • 【资料分析】刷题日记3
  • 代码随想录Day50|图论Part01,leetcode题目:98. 所有可达路径
  • 制作炫酷个人网页:用 HTML 和 CSS3 展现你的风格
  • JS基础之【对象详解 -- 对象的属性与方法、遍历对象与内置对象】
  • PCL 点云圆柱邻域搜索
  • 中国计算机学会(CCF)推荐中文科技期刊目录(2019年)
  • 【云原生监控】Prometheus之Alertmanager报警
  • SpringBoot 消息队列RabbitMQ 消息确认机制确保消息发送成功和失败 生产者确认
  • 什么是HTTP DDOS,如何防护
  • C++速通LeetCode中等第12题-矩阵置零(空间O(1)含注释)
  • xml中的转义字符
  • Java-使用反射来处理对象,并构建新的JSON数据结构
  • JavaScript标准库系列——Math对象和Date对象(二)
  • k个最大的数及变种小结
  • MySQL QA
  • Netty+SpringBoot+FastDFS+Html5实现聊天App(六)
  • python_bomb----数据类型总结
  • Python实现BT种子转化为磁力链接【实战】
  • Shadow DOM 内部构造及如何构建独立组件
  • 闭包--闭包之tab栏切换(四)
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 服务器之间,相同帐号,实现免密钥登录
  • 欢迎参加第二届中国游戏开发者大会
  • 基于Mobx的多页面小程序的全局共享状态管理实践
  • 开源中国专访:Chameleon原理首发,其它跨多端统一框架都是假的?
  • 适配iPhoneX、iPhoneXs、iPhoneXs Max、iPhoneXr 屏幕尺寸及安全区域
  • 我建了一个叫Hello World的项目
  • 小李飞刀:SQL题目刷起来!
  • 学习Vue.js的五个小例子
  • 原生JS动态加载JS、CSS文件及代码脚本
  • 在Docker Swarm上部署Apache Storm:第1部分
  • ​必胜客礼品卡回收多少钱,回收平台哪家好
  • ​低代码平台的核心价值与优势
  • # SpringBoot 如何让指定的Bean先加载
  • #565. 查找之大编号
  • #window11设置系统变量#
  • #Z2294. 打印树的直径
  • #我与Java虚拟机的故事#连载16:打开Java世界大门的钥匙
  • (10)ATF MMU转换表
  • (13):Silverlight 2 数据与通信之WebRequest
  • (3)Dubbo启动时qos-server can not bind localhost22222错误解决
  • (env: Windows,mp,1.06.2308310; lib: 3.2.4) uniapp微信小程序
  • (初研) Sentence-embedding fine-tune notebook
  • (二十九)STL map容器(映射)与STL pair容器(值对)
  • (几何:六边形面积)编写程序,提示用户输入六边形的边长,然后显示它的面积。
  • (六)库存超卖案例实战——使用mysql分布式锁解决“超卖”问题
  • (四)docker:为mysql和java jar运行环境创建同一网络,容器互联
  • (小白学Java)Java简介和基本配置
  • (转)C#调用WebService 基础
  • (轉貼) 2008 Altera 亞洲創新大賽 台灣學生成果傲視全球 [照片花絮] (SOC) (News)
  • (最新)华为 2024 届秋招-硬件技术工程师-单板硬件开发—机试题—(共12套)(每套四十题)
  • .MSSQLSERVER 导入导出 命令集--堪称经典,值得借鉴!