udp_socket

文章目录

UDP服务器封装

系统调用socket

创建套接字

返回值

socket返回依旧是一个文件,所以创建套接字的本质,底层就是打开一个文件,以前strcut file指向的是具体某一个磁盘上的设备,只不过我们的struct file指向的底层网卡设备,他就相当于一切皆文件。

有了对应的套接字之后未来就可以使用套接字来进行收发消息,但在进行各种收发之前,我们的服务器都必须得有一个参数socket的返回值,这个套接字创建之后呢,类比文件接口,把文件创建好得到了文件描述符,从此往后所有接口想对文件交互访问都得有fd,套接字的文件描述符同理。

问题

服务器绑定的端口 and IP地址是什么?

bind系统调用

要绑定就得用这个通用结构体,但是我们用的是sockaddr_in

每个字段都有细节

sin_zero 对应 填充 不管

通用类型结构体 头文件如图

bzero结构体清0

使用这个结构体需要先把他清空

然后我们就填中结构题字段就可以了

sin_family

sockaddr_in 里面有什么?我追进去怎么没看见sin_family字段?

利用了宏替换

sa_family_t 实际上是短整型,我们就填对应的16位地址类型,AF_INET

端口号

如果今天双方通信时,我给对方发消息,对方要发消息回我,他得知道我,我就得把端口号发给过他。

说明端口号的信息将来一定要能够发送给对方的,无论客户端还是服务器也罢。

协议一个字段都没学,但网络通信本质就是进程间通信,我要把我的端口号带上还有正常消息都给对方发过去,对方处理完也能拿着我的端口号响应给我。

结论就是端口号在网络里来回发送。

所以端口号填充到结构体里必须保证他是网络字节序,因为该端口号是要给对方发送的。

这个代码在你系统里面编译是小端,必须转大端。

ip地址

用户使用字符串IP传入也是字符串,而结构体中是要四字节的,字符串一个字符就是一字节明显不对应,所以需要转换

整数转字符串

字符串转整形 想告诉大家的是互相转难度不大

ip地址也要在网络当中发送,不然怎么回复与相应,客户端和服务器之间。

如果IP要被网络使用,ip出了转化成4字节ip,ip还必须是网络序列的。

赋值part1-part4都是在你本机进行的计算。

把IP地址转化成网络序列的话,无非就根据当前机器是大端小端,决定赋值的顺序,要么就是part1 = 100 or part1 = 192, part1是结构体中地址最小的,192是数值权重最高的,这样写就是大端,反过来就是小端。

所以只是决定part1 到part4赋值顺序,就可以更改我们当前IP报文形成四字节是网络序列还是主机序列。

  1. ip必须string转四字节Ip
  2. 四字节uint32_t 类型ip 还必须是网络序列的。
    上面图里这两个功能不用我们自己做

inet_addr

他做了两件工作 字符串转uint32_t + 转大端

至此这个结构体的信息只是在栈上,在用户空间而不是系统空间3-4G

所以还没有与套接字关联,设置进内核

UDP核心步骤,创建套接字+绑定

基本都是固定形式,UDP就这么多。

接下来做的工作仅仅是收发消息。

recvfrom

sendto

flag 发送方式 设置为0

新指令 netstat -naup (-nlup)

n能显示数字,就显示数字

a all所有

u udp

p 显示pid

只要能用netstat 查到我们进程./udpserver就说明我们的服务器已经启动了。

今天虽然启动了,但仅仅是巧合,这里面有坑,我们得点出来。

一个关于IP

你查到本地地址 绑定的IP是0.0.0.0,那你服务期的公网IP不是0.0.0.0啊,如果我们今天绑定服务器公网IP,你就会得到如下错误

云服务器禁止直接绑定公网ip,因为它做了虚拟化

bind(IP:0.0.0.0),凡是发给我这台主机的数据,我们都要根据端口号向上交付 --- 任意地址bind

因为服务器可能有两张网卡,两个Ip,你只绑定一个,另一个ip客户端的信息你就拿不上来

"0.0.0.0"字符串 转 uin32_t 本来就是0

所以结构体 的另一种写法

从今往后虚拟机可以用公网ip,但是云服务器就端口,ip就0就行

一个关于port

端口号 16位 范围0~65535

我们一般绑定8000+往上不会有问题,你非要绑系统内定就sudo 去绑,我们不建议

就想说ip绑0,端口号8000以上的,就完了。


客户端

client 需要socket创建套接字,socket创建的网络文件描述符不用就close 关掉

那client需要bind吗?

客户端一定要绑定,要有自己的ip和端口,这是套接字通信,客户端也要唯一性标识。

所以要!

只不过不需要用户显示的bind! 一般由os自由随机选择。

服务器的IP和端口不要一直变,不能随机绑定,让客户端找不到,他只能由程序员来绑是确定的。

而客户端的ip和端口是多少,其实不重要,只要保证主机上的唯一性就可以。

全是由客户端给服务器发信息,服务器就能知道客户端是谁,ip port如何如何

所以系统什么时候给我bind呢?

首次发送数据的时候!

那客户端怎么知道他要发给谁,请求那个服务器的ip port

这个工作由我们来做,通过命令行参数让用户输入请求的ip port

怎么发

1.发什么数据 -- 输入字符串

2.给谁发

我们可不止需要ip+port,同样需要构建struct sockaddr_in结构体

今天客户端有可能从不同的服务器收发消息吗?

客户端一气发给好几个服务器ip 的sendto,所以有可能

有可能,但今天我们就一个

最后客户端发什么字符串,服务器就给我返回什么字符串

就这样一来一回

域名其实就是ip地址

服务器一般做推广自己的域名ip,服务器的端口号约定好

今天我们客户端是利用命令行参数来进行直接绑定,服务器裸露自己的Ip和端口号

包装器 的两种类型重命名方式

你可以把包装器当成函数指针

包装器使用统一可调用类型

关键字 typedef 类型重命名

一般是重命名在默认类型 后面 ,函数指针是中间

把收发数据 和 处理数据 做解耦

让main函数中调用Run方法时传入一个func_t类型的可调用类型方法,处理完数据再把结果发回去

服务器收到消息把消息传递给我传进来的这个回调函数func,回调函数会把数据回调式的处理,处理完成之后把结果返回。

这样做的本质是对代码进行分层。

就是不要把字符串的处理放在我们的代码当中

直接使用我们传进来的方法,在上层不关心网络通信了,消息是什么样的做加工处理就行。你可以返回echo 服务期简单的处理,也可以传入不同的回调方法处理命令返回结果。

没人规定网络udp只能发送字符串,我们也可以认为发送的是命令啊,在服务器上创建进程再把命令执行的结果返回

这样写费时间,我们可以利用popen

系统调用popen

封装起来的管道,和子进程执行命令的应用,,popen作用是把执行命令以字符串的形式给我,popen底层我会帮你fork,我会让父子进程建立管道,让子进程把结果通过管道返回给调用方,调用方如果想得到command运行结果,你可以通过文件指针方式读取,type如果是r相当于读方式打开文件。

UDP应用场景

  1. ExcuteCommand
  2. 简单聊天室
  3. windows端的客户端访问Linux服务期
相关推荐
纷飞梦雪1 小时前
使用chroot预安装软件到ubuntu22中
linux·运维·ubuntu
不脱发的猴子2 小时前
Wireshark使用教程
网络·测试工具·wireshark
小羊在奋斗4 小时前
【Linux网络】NAT技术、DNS系统、五种IO模型
linux·网络·智能路由器
jiarg6 小时前
linux 内网下载 yum 依赖问题
linux·运维·服务器
yi个名字6 小时前
Linux第一课
linux·运维·服务器
Kurbaneli6 小时前
深入理解 C 语言函数的定义
linux·c语言·ubuntu
菜鸟xy..7 小时前
linux 基本命令教程,巡查脚本,kali镜像
linux·运维·服务器·kali镜像·巡查脚本·nmtui
暴躁的小胡!!!7 小时前
Linux权限维持之协议后门(七)
linux·运维·服务器·网络·安全
遇见火星7 小时前
2025年Linux 安全与运维指南
网络