Iinux:网络编程

发布时间:2026/6/2 6:15:16

Iinux:网络编程 网络编程基础知识发展历程协议TCP-IP协议传输控制协议以及因特网协议TCP/IP协议族体系结构应用层HTTP把OSP7层体系中的会话层、表示层、应用层合并到一个应用层TCP协议①面向连接②可靠传输③流量控制调整发送速度物理层与MAC地址IPV4逻辑地址IPV6是解决地址不够用的情况地址枯竭问题128位的地址MAC地址的作用场景核心职责局域网通信交换机通过MAC地址表转发帧ARP协议将目标IP地址解析为MAC地址局域网内安全过滤网络接入控制如MAC地址白名单流程封装帧---在物理层中转换为电信号通过网线传输----交换机处理将电信号还原成帧----主机B接收信号在物理层还原为帧MAC子层效验为MAC地址网络层与IP协议IP协议通过IP地址唯一标识设备IPV4:32位IPV6:128位ARP协议将IP地址解析成一个MAC地址RARP协议将MAC地址解析为IP地址IP数据包结构服务类型定义服务质量区分流量类别一个C类地址192.168.80.10可以知道它的网络号为192.168.80.0广播地址192.168.80.255网关192.168.80.1私有IP地址缓解IP地址短缺的问题A类2^24 -2 1677万个主机数目B类2^16 -2 65万C类2^8 -2 254子网掩码将大网络切割成小网络子网掩码用来区分网络部分和主机部分运作逻辑按位与运算子网的主机数量2^32-新掩码位数 -2如192.168.1.0/26;主机数为2^32-26-264-262可用IP范围为192.168.1.1~192.168.1.62 广播地址为192.168.1.63IPv6单播、组播、任播单播一对一类似于IPv4组播一对多取代IPv4的一个广播任播数据包发送到最近的一个一组设备中示例的写法2001:0db8:85::8a2e:0370:7374::代表连续0路由路由选择根据路由表取决定下一跳的地址路由表的生成方式是由静态配置管理员手动进行配置管理OSPF以及BGP协议数据包转发查表后从一个正确的接口进行发出NAT网络地址转发将私有IP转换成公有IP路由过程示例电脑私有IP访问百度服务器公网IP----这个公网IP不在本地网络查询路由表找到默认网关-----通过ISP网络逐跳进行转发最终到达百度服务区传输层与端口传输层使命是为了不同的主机的应用进程创建逻辑通信网络层使命负责主机到主机的通信传输层端到端的通信传输层两大核心服务可靠传输TCP不丢包、无失序、无重复到达高效传输UDP不可靠、无连接端口本质定义是一个16位的整数与IP地址共同组成套接字的一部分socket示例是IP与端口的组合192.168.1.100:8080占用一个8080的端口数据库3306端口的核心作用客户端通过访问不同的端口号去访问特定的一个服务服务标识服务端可以通过不同的端口同时去处理多个请求并发支持端口的大小0~65535分为共用端口0~1023是系统级服务需要申请管理员权限去访问它注册端口1024~49151是用户级的端口需要向INA进行注册使用动态端口49151~65535临时使用于客户端端口22SSH远程 80HTTP协议 443加密网页TCP、UDP协议音视频传输会使用到UDP协议传输层多路复用与解复用发送方复用将不同应用的数据封装到不同端口的报文段接收方解复用根据目标端口号将数据分发给正确的应用进程Socket IP地址 端口号 协议类型为什么要使用端口号由于IP的局限性不知道设备的应用需要门牌号部门的分机号端口冲突怎么解决端口冲突使服务端启动失败1、可以终止当前的端口进程2、更换服务端端口TCP、UDP它们的端口是否相互独立是独立比如TCP的80端口与UDP的80端口它们不会发生冲突应用层与常见架构模式应用层提供了给我们特定应用程序与网络服务的一个通信接口核心特性面向用户进行操作不同服务对应不同协议DNS用于域名解析webSocket用于实时通信HTTP用于web服务器与web浏览器之间相互传输超文本数据实现浏览器去访问万维网使用80端口/基于TCP协议实现HTTPS基于加密的网页进行传输基于43端口/TCP协议FTP用于在网络上传输文件的协议文件共享以及远程文件传输21/TCPSTMP:邮箱传输协议让邮箱实现发送以及接收邮件的功能DNS将URL域名解析成IP地址的协议域名-IP53/UDP架构模式C/S架构Client-Server——客户端-服务端架构核心思想客户端发送请求如微信桌面端服务端集中处理请求并相应如腾讯聊天服务区缺点维护成本高客户端-----HTTP请求-----web服务器-------响应数据---客户端B/S架构Browser-Server核心思想浏览器统一客户端如Chrome、Firefox服务区提供web服务Nginx、Apache应用层协议与架构模式的一些关联1、协议驱动架构选择HTTP/HTTPS天然适用于B/S架构的场景MQTT适用于物联网的C/S架构2、架构模式影响协议设计CS架构需要支持状态保持如FTP分控制通道和数据通道BS架构的协议需要无状态的如HTTP的无状态性依赖cookie和section的扩展协议与应用架构的关系:共生的关系协议是架构的血液如HTTP、FTP协议定义了数据的交换规则支撑架构的整体运行架构是协议的载体BS、CS架构决定了我们协议的使用场景以及优化方向持续远近功能传统CS到云衍生的微服务架构根据协议根据我们的协议以及技术不断地提升不断地发展套接字与网络字节序字节序的本质定义多字节数据如int、float在内存中的存储顺序两种类型·大端序网络字节序高地址存低位高位存的是低字节比如0x1234存储为1234小端序主机字节序高地址存高位低位存的是低字节比如0x1234存储为3412变量在内存里是从 低地址 开始存放的第一个字节 最低地址变量必须从 低地址 开始往 高地址 方向放大小端转换头文件#include arpa/inet.h1、htonl()函数 host-to-net-long作用主机→网络序32位如IPv4地址定义unsigned int2、htons()函数 host-to-net-short作用主机→网络序16位如端口号定义unsigned int3、ntohl()函数 net-to-host-long作用网络→主机序32位4、ntohs(函数 net-to-host-short作用网络→主机序16位如何将点分十进制转换为机器识别的数据inet_addr()函数作用将点分十进制字符串转换成网络字节序的无符号四字节整型inet_ntoa()函数作用将网络字节序的无符号四字节整型转换成点分十进制字符串函数原型:char *inet_ntoa(structin_addr in);Socket套接字基础TCP通信TCP与UDP对比对比TCPUDP角色快递员行使不管对方在不在送到就行不讲顺序与完整性特点严格控制准确率低优点可靠性强、顺序性、超时重传传输效率高实时性强速度快缺点开销大数据可能丢失、乱序丢包使用场景HTTP/HTTPS文件传输(FTP);邮件SMTP/IMAP视频流RTP、DNS查询、在线游戏、VoIP、轻量级交换、广播、组播消息TCP网络编程流程Socket()---bind()---listen()---accept()---send()/recv()---close().1.创建流式套接字--Socket()函数原型int socket(int domain,int type, int protocol);2.填充服务器的网络信息结构体--struct socketaddr_in3.将套接字于服务器的网络信息结构体绑定--bind服务器需要bind客户端不需要bind;listen之前需要bind客户端不需要去bind4.将套接字设置成被动监听状态--listen()5.阻塞等待客户端连接--accept()会处理套接字函数原型int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);参数sockfd表示处于监听状态的socketaddr用于保存客户端地址的结构体指针如果不关心客户端的信息可以直接传NULLaddrlen输入时为addr的缓冲区大小输出时为实际地址长度,如果不关心客户端的信息可以直接传NULL返回值成功返回新的socket文件描述符由内核生成代表着与返回客户端TCP连接专用于与客户端通信失败返回-1并重置错误码作用从全连接队列中去取出一个已经建立的连接然后创建一个socket用于数据传输进行一个队列的操作全连接队列为空进行一个阻塞等待状态内核会复制监听socket党的配置协议缓存区大小生成一个对应的可以与客户端连接通信的socket6、收发数据--recv()/send()recv函数核心作用通过socket去接收来自应用层的数据底层内核接收缓冲区拷贝数据到用户空间send函数参数sockfd表示客户端的socket套接字buf要发送的数据首地址len数据大小flags控制选项如MSG_DONTWAIT非阻塞MSG_PEEK窥视数据0阻塞返回值成功返回实际发送的数据字节数失败返回-1并重置错误码7、关闭套接字close函数作用减少文件描述符的引用计数底层原理多个进程共享socket的时候所有的进程都要调用close才能进行真正的关闭内核会释放套接字所占用的所有资源包括套接字的数据结构、缓冲区、以及正在等待的队列只有当所有的套接字进程退出或关闭时内核才会回收这个套接字的所有资源挥手TCP客户端TCP客户端的搭建流程socket() ---connect()-----send()/recv()----close()流程1.创建流式套接字-----socket()2.填充服务器的网络信息结构体---struct sockaddr_in3.与服务器建立连接--connect()connect函数头文件#includesys/socket.h函数原型int connect(int sockfd,const struct sockaddr *addr,socklen_t addrlen);connect是一个阻塞函数参数sockfd表示客户端的socket套接字addr表示目标服务器的地址结构体addrlen 地址结构体的长度返回值成功返回0失败返回-1并重置错误码核心作用触发三次握手;超时重传重新传输6次重传原理发送SYN包--接收SYN-Ark包----发送回应包Ark包4.收发数据--recv()/send()5.关闭套接字--close()TCP的三次握手和四次挥手TCP建立连接是通过三次握手实现的半连接队列与全连接队列流程三次握手发生在客户端的connect函数与服务端的accept函数之间区间过程第一次握手客户端发送一个携带SYN标志数据包(同步序列号)这个包表示客户端请求建立连接----客户端会进入一个SYN-SENY的状态发起方第一次发给接收方设置成的状态启动重传计时器第二次握手服务端收到请求之后回复一个SYN ACK标志的数据包进入半连接队列启动定时器表示服务端已经接收到了客户端的请求并同意建立连接服务区会选择一个随机的序列号b将它放置到带有SYN字段中将这个带有SYN标记的数据包放到ACK的字段中发回给客户端服务器会进入SYN-RCVD的一个状态就完成了第二次握手第三次握手客户端收到服务端发来的回复之后清空重传定时器把它设置为已连接分、再发送一个带有ACK回应标志的数据包表示客户端确认收到来自服务端的响应并同意建立连接客户端将服务端的一个初始序列号b,这个初始序列号加1放到ACK标志的一个字段中再将数据包重新发回到我们的服务器服务端收到ACK之后重新去创建一个新的socket从半连接队列中去删除旧的socket将新socket加入到全连接队列中然后从全连接队列中去取socket于是客户端、服务端都进入一个称为ESABLISHED的状态连接就建立完成了握手完成三次握手的过程保证了客户端与服务端都准备好去建立连接并且可以正确地发送与接收数据了如果服务器没有收到客户端的请求或客户端没有收到服务端的响应我们就重新发送请求直到建立连接成功三次握手保证了数据的可靠性与安全性避免了重复的连接请求以及资源浪费的情况为什么不能两次握手因为可能被中间商欺骗中间商篡改数据使客户端和接收端收的请求和响应都发生错误就像黑客而且不能确认对方身份三次握手可以确认彼此的身份确保可靠连接通信四次挥手通过挥手断开连接第一次挥手客户端发送FIN报文断开连接报文这个报文会指定一个序列号客户端会处于FIN-WAIT的状态等待断开连接第二次挥手服务端已经接收到了FIN报文回发一个ACK报文表示服务端收到了客户端的报文服务端会处于CLOSE-WAIT的状态第三次挥手服务器也想断开连接情况与客户端第一次挥手一样发送FIN报文FIN 1指定一个序列号seq w服务端会处于LASY-ACK的状态给服务端最后的一个回应第四次挥手客户端收到了我们的FIN报文收到来自于服务端请求的端口连接的一个报文客户端回复一个ACK回复报文作为应答并且我们将服务端的一个序列号的值加1 作为我们自己的ACK报文的一个序列值这时客户端会处于TIME-WAIT的状态——过一段时间——确保服务端收到了自己的回应报文才进入CLOSE状态这个TIME-WAIT等待时间是一个2MSL的时间通常是一个报文的一个回应时间大约为60秒服务端CLOSE后客户端也就处于一个CLOSE的状态为什么要四次挥手断开连接?取决于TCP的全双工特性TCP是双向独立关闭的特性客户端、服务端各自都有独立的发送通道以及接收通道一方发送FIN表示我们不会再给你发送消息但是我还能接收到来自对方的消息需要双方独立进行一个确认关闭为什么两次、三次挥手不行因为当我们的客户端发送完我们的FIN报文之后我们服务端可能还没有完成完全发送完的数据如剩余的响应需要发送ACK报文去确认客户端的一个关闭请求等待我们数据都发送完毕之后我们再去发送自己的一个FIN请求断开请求——即第三次挥手状态含义CLOSE-WAIT状态时服务器在接收到我们的FIN报文之后进入了这个状态进入这个状态时会等待我们的应用程序处理完剩余的数据我们才会发送我们的FIN请求FIN就是请求断开报文的含义TIME-WAIT状态是确保我们最后一个ACK回应我们到达服务器了如果丢失了服务器会重传我们的FIN报文然后我们再进行一个回应这样防止了旧链接的一个延迟报文去影响我们的一个新链接我们会等待一个2MSL的时间通常为60秒如果超过了这个时间我们没有再次收到FIN报文则代表对方成功收到的是ACK报文于是我们就进入CLOSE状态UDP通信1.无连接2.面向数据报UDP通信流程客户端方面1.创建套机字2.sendto()向目标地址发送数据不需要绑定本地的端口系统自动分配端口recvfrom()接收服务器返回的数据获取源地址信息3.调用完函数使用close();关闭套接字释放资源服务端方面1.创建套机字2.绑定端口通过bind()函数绑定固定端口如8888端口确保客户端可以精确地去发送数据给服务器3.recvfrom函数接收数据去阻塞等待来自于客户端的数据来获取数据以及客户端的地址4.sendto发送应答客户端的地址从recvfrom获取的地址精确发回客户端即回复数据5.调用close释放套接字、释放资源recvfrom函数头文件原型参数sockfdbuflenflags:控制选项如MSG_DONTWAIT非阻塞MSG_PEEK窥视数据0代表阻塞src_addr源地址获取发送方的信息如IP地址端口号将这个信息存到这个源地址这个结构体addrlen地址长度作用从接收缓冲区取出完整的UDP报文缓冲区为空会发生阻塞取出报文后会剥离UDP的头部并且将我们的数据拷贝到用户空间中然后记录源地址sendto函数socketbuf:发送的数据的首地址dest_addr:目的地址作用1、将用户地址拷贝到内核缓冲区中2、封装UDP头部源端口、目的端口、长度端、校验和3、交给IP层---路由---发送单播、组播和广播——搭建UDP的服务器和客户端单播一对一的通信流程与各层职责应用层调用rend---传输层-----网络层封装IP头部即单播通过路由表去转发;如默认网关----数据链路层ARP协议将目标IP的MAC地址封装以太帧单播MAC地址组播一对多的通信组播工作流程发送者1、创建套接字2、填充组播信息结构体3、发生数据接收者:1、创建套接字2、填充组播信息结构体3、将套接字与组播信息结构体绑定bind4、设置加入多播组setsockopt5、接收数据recvfromsetsockopt函数setsockopt函数头文件#include sys/socket.h函数原型:int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);参数sockfd目标套接字描述符表示需要配置的套接字level选项层级(如1、SOL_SOCKET通用套接字选项 2、IPPROTO_IPIPv4选项 3、IPPROTO_TCP选项)optname 选项名称(如S_REUSEADDR、IP_ADD_MEMBERSHIP)optval指向选项值的指针类型和长度需与optname匹配optlen optval指向的数据长度原理作用setsockopt函数是一个系统调用用户程序向内核去传递一个配置参数内核会根据参数去修改套接字相关联的一些协议栈大多数选项配置在套接字的生命周期内持续有效直到显示去修改配置或者套接字关闭才会失效构建广播发送端广播一对所有通信数据包发送到同一网络同一个局域网内的所有主机特点1、受限广播目标地址是一种特殊的网络地址为255.255.255.2552、定向广播目标地址为子网的广播地址192.168.1.255这个网络需要路由去去允许系统转发默认情况下是禁用这个状态避免广播风暴泛洪式的传输使用setsockopt函数去设置启用广播选项工作流程与原理发送者设置套接字为SO_BRODCAST选项表示运行去发送套接字广播包然后给广播包的目标地址设置成广播地址接收端设置套接字接听所有绑定指定的端口监听所有接口的数据网络设备交换机将广播包泛洪到所有的端口除了源端口然后路由器会默认去丢弃广播包防止跨子网进行传输默认禁用定向传播

相关新闻