【Linux】socket网络编程基础
个人主页~
socket网络编程基础
- 一、IP地址
- 1、概念
- 2、源IP地址和目的IP地址
- 二、端口号
- 1、概念
- 2、源端口号和目的端口号
- 三、TCP和UDP协议
- 四、网络字节序
- 五、网络通信的本质
- 六、全面认识网络通信
- 七、socket编程基础
- 1、调用接口
- (一)创建描述符
- (二)绑定端口号
- (三)监听套接字
- (四)接收请求
- (五)建立连接
- 2、sockaddr的结构
一、IP地址
1、概念
IP地址是在IP协议中,用来标识网络中不同主机的地址,它有两个版本,一个是IPv4
,一个是IPv6
,IPv4
是一个32位4字节的数字,通常使用点分十进制的字符串表示IP地址,例如192.168.1.1
,IPv6
是一个108位16字节的数字,一般来说,现在在世界上使用规模最大的就是IPv4
,但是因为4字节能表示的数字只有不到43亿,随着时代的进步,入网设备从电脑和手机逐渐变成了除了它们以外其他的例如空调、洗衣机、冰箱、智能音箱、智能门锁、电视等等,每一个智能设备都要有一个自己的IP地址,所以我们国家对于IPv6
的布置是战略性的,我国是世界上对于IPv6普及最广的国家,当然我们现在包括本文后面一般提到IP协议一般都是IPv4
2、源IP地址和目的IP地址
- 源 IP 地址:是指在网络通信中,发送数据的设备所使用的 IP 地址,它标识了数据的发送端,用于让接收方知道数据是从哪里来的,就如同信件上的寄件人地址一样
- 目的 IP 地址:是指数据要发送到的目标设备的 IP 地址,它标识了数据的接收端,指示数据应该被发送到哪里,类似于信件上的收件人地址
源IP地址和目的IP地址共同构成了网络通信的基础寻址体系,它们确保了数据在复杂的网络环境中能够准确、高效地传输,在数据发送前,发送设备会在 IP 数据包的头部封装好源 IP 地址和目的 IP 地址,然后数据在网络中传输时,路由器等网络设备会根据这些地址信息进行路由选择和数据转发,直到数据到达目的设备,整个网络通信过程就是围绕着源 IP 地址和目的 IP 地址进行的一系列数据封装、传输、路由和交付的操作
IP地址用于不同网络之间寻址,MAC地址用于同局域网传输
二、端口号
1、概念
端口号是传输层协议的内容
端口号是一个16位2字节的数字,用来标识一个进程并操作系统当前的这个数据要交给哪个进程处理
IP地址+端口号能够标识网络上的某一台主机的某一进程
一个端口号只能被一个进程占用,但一个进程可以绑定多个端口号
这里我们有问题了,主播主播,为什么端口号和进程pid都能标识一个进程,那他们分出来干啥呢?
其实,端口号与进程pid
,前者用来表示网络内容,后者用来表示系统内容,将网络和系统的内容进行解耦合,在一方出现问题的时候不影响另一方
2、源端口号和目的端口号
- 源端口号:是在网络通信中,发送数据的应用程序或进程所使用的端口号,它标识了数据的发送端应用程序或进程,使得接收方能够知道数据是由发送方设备上的哪个应用程序或进程发出的
- 目的端口号:是数据要发送到的目标应用程序或进程的端口号,它指定了数据应该被交付到目标设备上的哪个应用程序或进程,类似于在一个建筑物中指定具体的房间号
在网络通信中,源端口号和目的端口号与源 IP 地址、目的 IP 地址以及传输层协议(TCP 或 UDP)共同构成了完整的通信标识,IP地址能表示唯一的主机,端口号能标识该主机上的唯一一个进程,所以他们结合就可以找到我们指定的进程,当应用程序要发送数据时,会在传输层将数据封装成数据包,并在数据包中添加源端口号、目的端口号、源 IP 地址和目的 IP 地址等信息,在数据传输过程中,网络设备会根据这些信息进行数据的路由和转发,确保数据能够从源应用程序或进程准确地传输到目标应用程序或进程
三、TCP和UDP协议
- 基本概念
- TCP:是一种面向连接的、可靠的、基于字节流的传输层通信协议,它就像打电话,在数据传输前需要先建立连接,传输过程中会对数据进行确认、重传等操作以确保数据的完整性和准确性,传输结束后还需要关闭连接
- UDP:是一种无连接的、不可靠的传输层协议,它类似写信,不需要事先建立连接就可以直接发送数据,也不会对数据进行复杂的确认和重传操作,数据发送出去后就不管了,不保证数据一定能到达目的地或按顺序到达
- 特点
- TCP
- 面向连接:在数据传输之前,必须先建立连接,通过三次握手来确定双方的连接状态,确保数据传输的可靠性
- 可靠性:通过序列号、确认号、重传机制、流量控制和拥塞控制等手段,保证数据能够准确无误地到达目的地,并且保证数据的顺序性
- 字节流:将数据视为连续的字节流进行传输,没有明确的消息边界,应用层数据可以在任意时刻以任意大小发送
- 传输效率相对较低:由于需要进行连接建立、确认、重传等操作,TCP 的传输效率相对 UDP 较低,但在对数据准确性要求高的场景下是必要的
- UDP
- 无连接:发送数据前不需要建立连接,直接将数据报发送出去,减少了连接建立和拆除的开销,传输速度快
- 不可靠:不保证数据一定能到达目标主机,也不保证数据的顺序和完整性,可能会出现数据丢失、重复或乱序的情况
- 有消息边界:每个 UDP 数据报都有明确的边界,应用层一次发送的数据会作为一个完整的消息进行传输,接收方也会按照消息边界进行接收
- 传输效率高:没有复杂的确认和重传机制,UDP 的传输效率较高,适合对实时性要求高、允许一定数据丢失的场景
- TCP
四、网络字节序
在C语言的学习过程中,我们认识到内存(包括磁盘文件)当中的多字节数据相对于内存地址有大小端之分,实际上,网络上也有大小端之分,大端就是数据的高位字节存于低地址,低位字节存于高地址,小端就是数据的低位字节存于低地址,高位字节存于高地址
对于大端(小端)来说,对于 32 位整数0x12345678
,高位字节0x12
存于内存的低(高)地址,接着依次是0x34
、0x56
、0x78
存于更高(低)地址
网络字节序规定了在网络上传输数据时,统一采用大端序,如果主机是小端存储,在收到数据后,可以通过一些函数将大端数据转化成小端,下面是C语言的函数
#include
uint32_t htonl(uint32_t hostlong);//将一个32位无符号整数从主机字节序转换为网络字节序
uint16_t htons(uint16_t hostshort);//将一个 16 位的无符号整数从主机字节序转换为网络字节序
uint32_t ntohl(uint32_t netlong);//将一个 32 位的无符号整数从网络字节序转换为主机字节序
uint16_t ntohs(uint16_t netshort);//将一个 16 位的无符号整数从网络字节序转换为主机字节序
五、网络通信的本质
当我们进行网络之间通信的时候,比如我们在微信上发送一个hello world,首先我们要打开微信,然后输入发出,然后另一个用户在微信上收到hello world,这个过程实际上,将中间很多过程都忽略掉,就是两个进程在进行进程间通信,当我们以这个视角看待网络通信的时候,那么网络通信的过程也就成了一种介质,类似于管道或者共享内存一样的通信信道
六、全面认识网络通信
在 TCP/IP 四层模型中,每一层都包含了多种不同的协议,这些协议各自承担着不同的功能,共同协作以实现网络通信,下面这些内容需要的看一下,这里主要是指出每层都有多种协议,所以在数据解析的过程中,都是通过报头里面的源xx号和目标xx号起到的作用,精确找到要找到哪个协议解析
-
网络接口层
网络接口层负责将数据帧从一个节点传输到另一个节点,处理与物理网络的连接和数据传输,该层常见的协议有:- 以太网协议(Ethernet):是目前应用最广泛的局域网技术,定义了局域网中数据帧的格式和传输规则,以太网帧包含源 MAC 地址、目的 MAC 地址、类型字段和数据等部分,用于在局域网内进行数据的传输和交换
- Wi - Fi 协议(IEEE 802.11):用于无线局域网通信,有多个不同的标准版本(如 802.11a、802.11b、802.11g、802.11n、802.11ac、802.11ax 等),每个版本在传输速率、频段、覆盖范围等方面有所不同
-
网络层
网络层主要负责将数据包从源主机传输到目标主机,进行路由选择和寻址,该层的常见协议有:- 网际协议(IP):是 TCP/IP 协议族的核心协议之一,分为 IPv4 和 IPv6 两个版本,IPv4 使用 32 位地址,目前地址资源日益紧张;IPv6 使用 128 位地址,能够提供大量的地址空间,IP 协议负责将数据包从源主机通过网络路由到目标主机,它只提供尽力而为的服务,不保证数据包的可靠传输
- 互联网控制报文协议(ICMP):用于在 IP 主机、路由器之间传递控制消息,如网络连通性测试(ping 命令就基于 ICMP 协议)、路由错误报告等,ICMP 报文封装在 IP 数据包中传输
- 地址解析协议(ARP):用于将 IP 地址解析为对应的 MAC 地址,在局域网中,当一台主机要向另一台主机发送数据时,需要知道目标主机的 MAC 地址,ARP 协议通过广播 ARP 请求来获取目标主机的 MAC 地址
- 逆地址解析协议(RARP):与 ARP 相反,RARP 用于将 MAC 地址解析为 IP 地址,常用于无盘工作站等设备,这些设备知道自己的 MAC 地址,但需要通过 RARP 协议获取 IP 地址
-
传输层
传输层负责提供端到端的可靠通信或高效的数据传输服务,常见的协议有:- 传输控制协议(TCP):是一种面向连接的、可靠的传输协议,TCP 通过三次握手建立连接,在数据传输过程中提供确认、重传、流量控制和拥塞控制等机制,保证数据的可靠传输和顺序性,常用于对数据准确性要求较高的应用,如文件传输、电子邮件、网页浏览等
- 用户数据报协议(UDP):是一种无连接的、不可靠的传输协议。UDP 不保证数据的可靠传输和顺序性,但具有传输效率高、开销小的特点,常用于对实时性要求较高、允许一定数据丢失的应用,如实时视频和音频流、游戏等
-
应用层
- 超文本传输协议(HTTP):用于在 Web 浏览器和 Web 服务器之间传输超文本(如 HTML 页面),是互联网上应用最为广泛的一种协议。HTTP 是无状态的协议,每次请求都是独立的
- 安全超文本传输协议(HTTPS):是 HTTP 协议的安全版本,它在 HTTP 的基础上加入了 SSL/TLS 协议进行加密和身份验证,保证数据在传输过程中的安全性和完整性,常用于在线支付、登录等安全要求较高的场景
- 文件传输协议(FTP):用于在不同主机之间进行文件的上传和下载,提供了可靠的文件传输服务。FTP 使用两个 TCP 连接,一个用于控制命令的传输,另一个用于数据的传输
- 简单邮件传输协议(SMTP):用于发送电子邮件,它规定了邮件客户端如何将邮件发送到邮件服务器,以及邮件服务器之间如何进行邮件的转发
- 邮局协议(POP3):用于接收电子邮件,允许用户从邮件服务器上下载邮件到本地客户端。
- 互联网消息访问协议(IMAP):也是用于接收电子邮件的协议,与 POP3 不同的是,IMAP 允许用户在邮件服务器上管理邮件,而不仅仅是下载邮件到本地
- 域名系统(DNS):用于将域名解析为对应的 IP 地址,当用户在浏览器中输入域名时,DNS 服务器会将域名转换为对应的 IP 地址,以便浏览器能够找到对应的 Web 服务器
七、socket编程基础
1、调用接口
(一)创建描述符
#include
int socket(int domain, int type, int protocol);
返回值:成功返回套接字描述符sockfd
,失败返回-1
domain
:指定通信域
通信域 | 意义 |
---|---|
AF_INET | IPv4网络协议 |
AF_INET6 | IPv6网络协议 |
AF_UNIX 或 AF_LOCAL | 用于本地通信,可在同一台机器的不同进程间进行高效数据传输 |
type
:指定套接字类型
套接字类型 | 意义 |
---|---|
SOCK_STREAM | 流式套接字,基于TCP实现 |
SOCK_DGRAM | 数据报套接字,基于UDP实现 |
SOCK_RAW | 原始套接字,允许程序直接访问底层网络协议 |
protocol
:指定了使用的具体协议,通常将其设为 0,这样系统会根据 domain
和 type
自动选择合适的协议
(二)绑定端口号
#include
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
返回值:成功返回0,失败返回-1
sockfd
:要进行绑定的套接字描述符
addr
:一个指向 struct sockaddr
类型的指针,它存储了要绑定的地址信息,具体的结构在下个话题中说
addrlen
:这是 addr
所指向结构体的长度,通常使用 sizeof
运算符来获取,这里位输入型参数
(三)监听套接字
#include
int listen(int sockfd, int backlog);
返回值:成功返回0,失败返回-1
sockfd
:要监听的套接字描述符
backlog
:指定请求连接队列的最大长度,当有多个客户端同时发起连接请求时,服务器无法立即处理所有请求,这些未处理的连接请求会被放入一个队列中等待处理,backlog
就是这个队列的最大长度,如果队列已满,新的连接请求将被拒绝
(四)接收请求
#include
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
返回值:成功返回一个新的套接字描述符,这个新的套接字专门用于与发起连接请求的客户端进行数据传输,原来的 sockfd
仍然用于继续监听其他客户端的连接请求
sockfd
:这是由 socket
函数创建、bind
函数绑定地址和端口,并且通过 listen
函数设置为监听状态的套接字描述符
addr
:一个指向 struct sockaddr
类型的指针,它存储了发起连接请求的客户端的地址信息
addrlen
:这是一个指向 socklen_t 类型的指针,用于传入 addr 所指向结构体的长度,并且在函数返回时,该指针指向的值会被更新为实际存储的客户端地址信息的长度,这里是输入输出型参数
(五)建立连接
#include
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
返回值:成功返回0,失败返回-1
sockfd
:要连接的套接字描述符
addr
:存储了要连接的服务器的地址信息
addrlen
:表示 addr
所指向的地址结构体的长度,通常使用 sizeof
运算符来获取,输入型参数
2、sockaddr的结构
sockaddr
的结构如下图左一所示,实际上,我们在函数中用到的结构体是右边两个而不是左一,在sockaddr
接受传来的参数时,它会通过判断前面16位2字节的地址类型是AF_INET
还是AF_UNIX
,然后在使用时通过强制转化转换成sockaddr_in
或 sockaddr_un
,前者用于网络间通信,后者用于域间通信即进程间通信
今日分享就到这里了~
本文地址:https://www.vps345.com/10846.html