UDP_SOCKET编程实现

文章目录

socket编程接口

socket常见接口API:

认识struct sockaddr

网络套接字编程时,socket也分很多类:

1.unix socket:域间socket->用的是同一套接口, 不过用的是同一台机器上的文件路径,类似命名管道,负责本主机内部进行通信

2.网络socket:ip+port 网络通信(也可实现本地socket)(重点)

3.原始socket(应用层直接访问数据链路层,一般用于编写一些网络工具)

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


由于历史原因, 当初设计的时候不支持void*的通用接口

所以使用这样的方式

编写一个server服务

实现一个服务:

封装一个udpserver

构建服务基本框架:

UdpServer.hpp

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

Main.cc

cpp 复制代码
	#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

cpp 复制代码
	#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

cpp 复制代码
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完成

相关推荐
明天…ling2 小时前
Web前端开发
前端·css·网络·前端框架·html·web
MonkeyKing_sunyuhua2 小时前
安装 `privoxy` 将 Socks5 转换为 HTTP 代理
网络
pemper_3 小时前
数据不出境------IP证书申请
网络·网络协议·tcp/ip·http·https·ssl
Jack黄从零学c++3 小时前
自制网络连接工具(支持tcpudp,客户端服务端)
linux·c语言·开发语言·网络协议·tcp/ip·udp·信息与通信
网络研究院3 小时前
大型语言模型 (LLM) 劫持攻击不断升级,导致每天损失超过 100,000 美元
网络·人工智能·安全·语言模型·攻击·劫持
网络研究院4 小时前
企业急于采用人工智能,忽视了安全强化
网络·人工智能·安全·工具·风险·企业
mingzhi615 小时前
应届生必看 | 毕业第一份工作干销售好不好?
网络·web安全·面试
白帽黑客cst5 小时前
网络安全(黑客技术) 最新三个月学习计划
网络·数据结构·windows·学习·安全·web安全·网络安全
网络研究院5 小时前
网络安全:建筑公司会计软件遭受暴力攻击
网络·安全·研究·漏洞·报告·分析