Linux:udp socket编程

本文详细介绍了UDP套接字编程的基本流程,包括客户端和服务端的准备工作。服务端创建套接字并绑定地址,客户端创建套接字但通常不绑定地址。在通信过程中,UDP客户端先发送消息,服务端随后接收。涉及的关键概念包括套接字描述符、地址信息绑定、字节序转换函数以及发送和接收函数。同时,文章提到了UDP的发送和接收缓冲区,并简单提及了公网IP和私网IP的区别。
摘要由CSDN通过智能技术生成

ip+端口=套接字,现在所说的socket编程就是套接字编程
在这里插入图片描述

编程流程

对于网络编程要从客户端和服务端来看,在网络通信前,双方都要做准备工作:

对于服务端

1.创建套接字
2.绑定地址信息
绑定地址信息是绑定网络IP和进程端口

  • 例如,现在有一个服务端进程,绑定地址信息是为了有一个能标识自己在哪一个进程的端口;
  • 一个端口只能被一个进程绑定;
  • 当客户端需要连接该进程只需要拿到端口

对于客户端

1.创建套接字
2.不推荐绑定地址信息
不推荐绑定地址的原因:

  • 因为一个端口只能被一个socket结构体占用
    一旦客户端绑定了固定的地址,这个客户端只能运行一个
    并且还有端口冲突的风险
  • 可以让程序在同一机器上启动多个,绑定端口后每个主机就只能启动一个
  • 但是这只是我们没有绑定,而实际操作系统会在调用sendto函数发送数据前自动绑定一个端口

前期准备工作完成后,客户端和服务端就能相互发送消息

在发送消息时,一定是UDP客户端先给服务端发消息,因为服务端是不知道客户端在哪个IP和端口

  • 图示:
    在这里插入图片描述
  • 创建套接字:建立进程与网卡之间的关联
  • 绑定地址信息:给创建的socket结构体内部填充源IP和端口
    告诉系统收到的数据凡是地址和端口是我绑定的,就交给我处理
    发送数据的时候,源IP就是绑定的地址信息
  • 接收数据:从内核的socket结构体中的接收缓冲区取出数据
  • 发送数据:将数据放到内核scoket结构体的发送缓冲区中

在这里插入图片描述

创建套接字

在这里插入图片描述

  • 套接字描述符本质是文件描述符
  • 返回值是fd,就能以读写文件的方式来访问网络
    所以套接字实质是一块内存

绑定地址信息

在这里插入图片描述

  • 套接字可以用于网络通信和主机通信,不同通信方式,两个进程所需要的同一份资源不同
  • 所以设计了这个结构体来区分通信类型
  • 对于主机内通信,则传路径就行,找到一个文件
  • 将右边两个结构体对象传给sockaddr,用于解析是哪两个通信类型

定义一个通用类型结构体就是为了接收不同的结构体;
结合上图右边的蓝色框起部分理解
在这里插入图片描述

  • 在使用bind函数绑定地址信息时,需要对bind函数的第二个参数进行赋值
  • 也就是对sockaddr_in或sockaddr_un结构体中的变量进行赋值
  • 结构体中有两个普通类型变量sin_family(地址域信息),sin_port(端口)
  • 还有一个结构体变量sin_addr,该结构体内部的变量类型是一个无符号的32位整数,s_addr;要使用inet_addr函数转换
  • 在这里插入图片描述
  • 结构体第三个参数应传私网ip地址
  • sin_family:套接字用于网络通信还是主机通信
  • sin_port:填充对应的端口号信息,要发给对端主机,所以要转成网络字节序
  • sin_addr:
    字符串风格的点分十进制,每个区域是一个字节的数据
    在这里插入图片描述

addr:

不管是哪种地址结构,只要拿到前两个字节的数据,就知道剩下的数据该如何解析

接收与发送函数

在这里插入图片描述
sendto
peer是程序员填写的,用于给谁发

recv
peer:输出型参数,用来接收数据,是谁发送的拿到后进行解析
存的谁,就是信息谁发送给我的,由函数设置
alen:输入输出型参数,表示想要接收的地址信息长度,以及实际得到的地址信息

服务端代码在这里插入图片描述

  • sendto函数的peer参数,因为通过recvfrom函数获取到了客户端的IP和端口信息,所以发送的时候直接把peer原本的内容填进去就行,就可以发给收到消息的客户端了
  • 所以客户端要写一个socket_int类型的addr对象,把要访问的IP和端口预先处理好,让发送函数发送对端

客户端代码
在这里插入图片描述

客户端先发送再接收
服务端先接收再发送

字节序接口

uint_16t htons(uint_16t val)
uint_16t ntohs(uint_16t val)

typedef uint32_t in_addr
in_addr_t inet_addr(const char* ip);将点分十进制的字符串ip地址转换为网络字节序的整数IP地址
const char* inet_ntoa(struct in_addr addr),将网络字节序整数IP地址,转换成一个点分十进制字符串IP地址

ifconfig执行后,看lo和eth0的inet IP地址
端口使用1024以上的端口,0-1023端口已经被知名服务使用了

udp的发送接收缓冲区

  • 创建套接字后,会在内存中创建一个套接字对应的结构体;
  • 在该结构体中,根据创建套接字的不同类型(udp类型和tcp类型),都会产生两个缓冲区;
  • 一个是发送缓冲区,一个是接收缓冲区(缓冲区在传输层),创建套接字就相当于初始化这两个缓冲区
  • 调用sendto函数发送数据,该数据先会递交给udp的发送缓冲区当中
  • 调用recvfrom函数接收数据,是从接收缓冲区中拿数据

upd是有发送和接收缓冲区,因为udp是整条数据交付的,应用层将数据给udp后,udp就会在发送缓冲区打上udp的包头,递交给网络层的IP协议

  • 程序员基本是与传输层进行交互;
  • 不参与传输层和网络层,与网络层和数据链路层;
  • 这两者是靠net代码进行交互的

公网ip和私网ip

为什么有公网ip和私网ip

  • ipv4版本的ip地址本质是一个无符号的32位整数,约为42亿9千万个不同ip;
  • 但是全球实际的机器不止于此;
  • 所以将其中部分ip取出,让这部分ip不能直接访问互联网;
  • 但是这些ip可以在不同网络中进行附用;
  • 而公网ip可以直接访问互联网;

后面再详述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值