hello~ 很高兴见到大家! 这次带来的是Linux网络中关于网络基础这部分的一些知识点,如果对你有所帮助的话,可否留下你宝贵的三连呢?个 人 主 页: 默|笙文章目录一、Echo sever v1代码1.1 给程序占好本机的 IP 端口1. socket (创建套接字对象)2. 填充 sockaddr_in (准备地址信息)3. bind socket信息1.2 发送和接收信息1. 接收信息2. 发送信息1.3 ip地址介绍1. 本地回环地址 127.0.0.12. 局域网 IP 内网 IP私有 IP3. 公网 IP4. 特殊监听地址 0.0.0.01.4 服务端与客户端差异二、Chat serverv3代码代码gitee代码一、Echo sever v1代码1.1 给程序占好本机的 IP 端口1. socket (创建套接字对象)socket 系统调用的作用其实就是制造一个 socket 对象。由于 Linux 里面一切皆文件如果创建成功的话会返回套接字对应的文件描述符失败则返回 -1。这个套接字后续可以间接和网卡关联。现在刚创建好的 socket 对象相当于是一个空房间socket 本身已经是内核里特殊的套接字文件类型不是 bind 之后才变成网络文件只有调用 bind 之后相当于给这个空房间加上门牌号IP 端口外部主机才能根据这个门牌号找到这个房间。第一个参数是地址族协议域最常用的就是IPv4给它传递AF_INET。第二个参数用来决定通信模型常用的有 TCP 和 UDP 两种TCP 使用面向连接的字节流模型写SOCK_STREAMUDP 使用无连接的数据报模型写SOCK_DGRAM。第三个参数用来指定传输层协议选定 domaintype 的组合后通常只有一种默认协议大部分情况下直接写 0由系统自动选择对应协议。int_sockfdsocket(AF_INET,SOCK_DGRAM,0);2. 填充 sockaddr_in (准备地址信息)structsockaddr_inlocal;local.sin_familyAF_INET;local.sin_portntohs(_port);//手动将端口号存储方式转为大端local.sin_addr.s_addrinet_addr(_ip.c_str());我们要将 ip 和端口号信息塞进专门存储地址信息的对象也就是sockaddr_in结构体需要指定协议域、端口号和 IP 地址。这一步通俗来讲其实就是准备好空房间的门牌号信息暂时还没有贴到房间socket上。网络传输统一规定使用大端网络字节序。主机可能是小端或者大端所以填充结构体时端口号和 ip 地址必须转成大端。用 htons 函数可以进行转换。我们日常看到的192.168.1.12是点分十进制字符串方便人类阅读但内核需要的是 4 字节整数所以 IP 相比端口多这一层「字符串→4 字节整数」的转换。使用inet_pton/inet_addr函数可以一步到位不用再使用 htons 函数。3. bind socket信息bind 的返回值就比较普通了失败返回 -1并设置 errno成功返回 0。第一个参数是 socket 对象对应的文件描述符第二个参数传递填充好的地址结构体指针我们代码里一般传sockaddr_in需要强制转为sockaddr*第三个参数是这个地址结构体所占字节大小。这几个参数的作用就是把 socket 对象和填充好的地址信息绑定在一起。-----解决问题如何将 socket 对象填充好的地址信息绑定在一起。这一步就是将门牌贴到对应的空房间上面。intnumbind(_sockfd,(sockaddr*)local,sizeof(local));1.2 发送和接收信息1. 接收信息UDP 发送数据使用recvfrom函数失败返回-1成功返回实际接收的字节数。第 1 个参数sockfd通过什么接收socket 文件描述符也就是我们前面创建的 socket 对象。 第 2 个参数buf**把接收到的数据放到哪里**存放到待接收数据的缓冲区。第 3 个参数len这个缓冲区的大小。第 4 个参数flag怎么接收接收选项填0就是默认阻塞接收。第 5 个参数src_addr是谁发送的用来接收发送方的地址信息sockaddr 结构体包含对方 IP 端口。第 6 个参数addrlen是指针传入时放 src_addr 结构体的大小函数调用结束后会被修改为实际地址结构体长度。2. 发送信息UDP 发送数据使用sendto函数失败返回-1成功返回实际发送的字节数。第 1 个参数sockfd通过什么发送socket 文件描述符就是我们前面创建的 socket 对象。第 2 个参数buf发送什么存放待发送数据的缓冲区。第 3 个参数len待发送数据的字节长度。第 4 个参数flags怎么发送发送选项填 0 就是默认阻塞发送。 第 5 个参数dest_addr发送给谁目标主机的地址信息sockaddr 结构体包含对方 IP 端口。第 6 个参数addrlendest_addr 结构体的大小。1.3 ip地址介绍1. 本地回环地址 127.0.0.1范围127.0.0.0 ~ 127.255.255.255最常用127.0.0.1。特点只在当前这台主机内部通信数据包不会走出本机网卡不会发到网线 / 局域网。用途本地测试服务端、客户端。比如你的 UDP 服务端绑定127.0.0.1只有本机上的程序能连接访问别的电脑连不上。2. 局域网 IP 内网 IP私有 IP专门给同一个局域网内部设备使用路由器不会把这类数据包转发到互联网。私有 IP 三段10.0.0.0 ~ 10.255.255.255172.16.0.0 ~ 172.31.255.255192.168.0.0 ~ 192.168.255.255家里路由器最常见如192.168.1.12特点同一个路由器下手机、电脑互相通信不能直接在公网路由出外网需要路由器做 NAT 地址转换不同局域网之间可以重复使用同一套内网 IPA 家电脑192.168.1.2B 家电脑也可以是192.168.1.2互不冲突bind 绑定内网 IP同局域网别的电脑可以连你的服务外网不能直接访问。3. 公网 IP由运营商分配互联网上唯一全球不能重复。数据包可以在整个互联网路由外网的其他主机可以直接访问你。现在家庭宽带大多不是独立公网 IP是运营商 NAT 后的共享公网 IP。服务端绑定公网 IP互联网上任意主机都可以访问你的程序。家庭电脑没有独立公网 IP 时外网客户端无法直接连接本机服务。4. 特殊监听地址0.0.0.0监听上面所提到过的所有类型地址。如果服务端 bind 绑定具体 IP 地址那么它就只能收到客户端发给那个具体地址的信息而无法收到目的 IP 是其他地址的信息。而一台电脑它是拥有多个 ip 地址的我们的目标是只要是发给这台电脑该端口的数据包就都应该接收而不是限定到某个特定 IP 地址。这时就需要绑定0.0.0.0代表监听本机全部网卡与所有 IP。1.4 服务端与客户端差异服务端需要显性绑定 IP 地址和端口号其中 IP 地址绑定0.0.0.0客户端一般不手动 bind 显性绑定。如果客户端手动绑定固定端口号一旦多个客户端程序绑定同一个端口号就会发生端口冲突无法同时运行。所以客户端端口交给操作系统自动分配空闲临时端口本机 IP 地址内核本身可以自动获取。客户端在第一次调用 sendto 发送消息的时候内核会完成隐式绑定本机 IP 随机临时端口。二、Chat serverv3代码我们需要在 v1 版本代码的基础上对现有功能进行扩展与完善。当客户端数量增多时服务端需要对所有接入的客户端进行统一管理。我们可以通过先描述客户端地址信息、再对客户端集合进行组织管理的思路实现该需求为此新增两个类InetAddr信息描述类与 UserManager用户管理类。InetAddr 类提供两个构造函数一个基于 sockaddr_in 结构体构造另一个通过传入 IP 地址与端口号构造。创建该类对象时自动完成两种地址表示形式的相互转换。UserManager 负责管理所有接入服务端的客户端存储并维护客户端对应的 InetAddr 对象。Route 类作为服务端与 UserManager 之间的中间调度模块一方面保证对UserManager 的所有访问操作具备线程安全另一方面实现消息广播逻辑。今天的分享就到此结束啦,如果对读者朋友们有所帮助的话,可否留下宝贵的三连呢~~让我们共同努力, 一起走下去!