当前位置: 首页 > news >正文

【Linux】网络部分——网络基础(Socket 编程预备)

32.网络基础——Socket 编程预备

文章目录

  • 32.网络基础——Socket 编程预备
      • 端口号
        • 端口号与进程ID
      • 传输层的典型代表——TCP与UDP
        • 字节流与数据报的通信模型对比
      • 网络字节序
        • 计算机数据存储的大小端问题
      • socket接口编程
        • struct sockaddr
        • sockaddr 结构
        • socket编程常用API

端口号

IP地址用于标识主机的唯一性,但数据传输到目标主机并非最终目的,真正的目的是将数据交付给主机内的特定进程。在网络通信中,进程是用户在系统中的代表,数据必须交付给特定进程才算完成通信任务。操作系统中的传输层和网络层虽然只有一套,但上层进程可能有多个,因此需要端口号来标识特定进程。

  • 端口号是传输层的内容,是一个16位的整数,用于告诉操作系统将数据交付给哪个进程处理。
  • IP地址标识全网唯一主机,端口号标识主机内唯一进程,两者结合可以唯一标识网络中的特定进程。IP地址和端口号在网络通信中扮演着不同但互补的角色。IP地址用于标识网络中唯一的主机,而端口号则用于标识主机内唯一的进程。每个网络进程启动时都需要从传输层申请一个端口号与之关联。

在这里插入图片描述

  • 端口号的划分:
    • 0 - 1023: 知名端口号, HTTP, FTP, SSH 等这些广为使用的应用层协议, 他们的端口号都是固定的
    • 1024 - 65535: 操作系统动态分配的端口号. 客户端程序的端口号, 就是由操作系统从这个范围分配的
  • 网络通信的本质是进程间的通信,而非简单的主机间数据传输。网络通信中数据传输到目标主机只是手段,真正的目的是将数据交付给特定进程。在操作系统中,用户的所有行为最终都会转化为进程或线程的执行。当用户进行网络通信时,实际上是用户进程将数据交给网络,经过操作系统各层的处理后,最终由目标主机的操作系统将数据交付给目标进程。网络通信遵循端到端原则,即通信的起点和终点都是应用层的进程。
  • 端口号与IP地址的组合形成了网络通信的完整地址标识,即套接字(socket)
端口号与进程ID

端口号的存在是为了在网络层独立标识进程的唯一性,而不依赖于操作系统的进程管理机制(如PID)。虽然PID可以唯一标识进程,但将其引入网络层会导致网络模块与进程管理模块的强耦合。端口号的设计使得网络协议栈能够独立于进程管理运行,提高系统的解耦性。

传输层的典型代表——TCP与UDP

传输层有两个典型协议,tcp和udp。tcp协议(Transmission Control Protocol)提供有连接和可靠传输服务,通信前需要建立连接,保证数据传输的可靠性,如数据丢包重传、报文去重和乱序重排。udp协议(User Datagram Protocol)提供无连接和不可靠传输服务,直接通信,不保证数据传输的可靠性。tcp和udp在代码实现上的区别主要体现在连接建立和传输可靠性上。tcp适用于需要可靠传输的场景,如文件传输、网页浏览等;udp适用于实时性要求高、允许少量数据丢失的场景,如视频流、在线游戏等。

TCPUDP
传输层协议传输层协议
有连接无连接
可靠传输不可靠传输
面向字节流面向数据报
字节流与数据报的通信模型对比

字节流通信类似自来水供应,数据无边界,接收方可按需读取(如文件写入后读取困难);数据报则像快递包裹,收发边界严格对应(如UDP报文)。字节流由用户层解释内容(如管道一次读取多次写入的数据),数据报则需按发送格式解析。这种差异影响协议设计:TCP基于字节流,UDP基于数据报。

网络字节序

计算机数据存储的大小端问题
  • 多字节数据存储存在大小端之分:小端模式将低权位数据存于低地址(如0x123344e1e1存于起始地址),大端模式反之。

  • 在网络通信中,不同主机可能存在大小端不一致的问题,导致数据解释错误。小端主机发送数据到大端主机时,数据会被错误解释。为了解决这个问题,有人提出通过软件方案,在报文中使用一个字节标识大小端,但这种方案无法解决根本问题,因为无法确定哪个字节是标识字节。也有人建议统一硬件厂商的大小端标准,但实施难度大,涉及已售硬件和兼容性问题。最终解决方案是网络规定所有数据采用大端序列,小端主机发送数据前需转换为大端,接收时再转换回小端。操作系统会自动处理这些转换,确保通信正确。

  • 网络通信中,操作系统提供主机转网络和网络转主机的接口,如htonshtonl,用于处理端口号和IP地址的大小端转换IP地址在网络中以32位数字形式传输,而非字符串形式,以提高传输效率。字符串形式的IP地址(点分十进制)可转换为32位网络格式,反之亦然。通过指针和结构体操作,可以方便地进行这种转换。

  • 网络数据发送时,主机从发送缓冲区按内存地址从低到高的顺序发送数据,先发送低地址数据,后发送高地址数据。接收端主机将收到的字节按同样顺序保存到缓冲区。报文头通常位于高权值位,便于先获取报头信息再处理数据。

socket接口编程

网络通信中使用的套接字编程种类较多,最常见的有三种类型:网络套接字(network socket)、本地套接字(local socket,也称为Unix域套接字或Unix domain socket)以及原始套接字(raw socket)。

  • 网络套接字既可以用于本地通信,也可以用于网络通信,是网络通信中的最终解决方案。
  • 本地套接字仅用于本地通信,类似于网络版本的管道,这里不做说明。
  • 原始套接字通常用于编写网络工具,与业务开发无关。
struct sockaddr

​ 操作系统设计者在设计套接字接口时,考虑到不同种类的套接字可能导致接口数量激增且相似性高,对用户不友好,因此决定统一接口。为了实现接口的统一性,操作系统内部定义了一种通用的数据结构,即struct sockaddr,用于封装不同种类的套接字通信参数。无论是网络通信还是本地通信,用户都需要向操作系统传递参数,而操作系统通过统一的接口处理这些参数。网络通信需要传递IP地址和端口号,本地通信则通过文件路径标识通信双方。由于C语言不支持函数重载,操作系统设计了一种通用的接口struct sockaddr,用户在实际使用时需要进行强制类型转换。

  • 实际通信时可能需要使用更具体的结构体,如struct sockaddr_in(用于网络通信)或struct sockaddr_un(用于本地通信)。用户在调用接口时,需要将具体结构体的地址强制转换为struct sockaddr类型。操作系统内部通过结构体中的前16位字段(地址类型或协议族)区分通信类型,例如AF_INET表示网络通信,AF_UNIX表示本地通信。这种设计类似于多态的思想,即统一接口但内部实现不同。

在这里插入图片描述

sockaddr 结构
struct sockaddr{__SOCKADDR_COMMON (sa_);	/* Common data: address family and length.  */char sa_data[14];		/* Address data.  */};struct sockaddr_in{__SOCKADDR_COMMON (sin_);in_port_t sin_port;			/* Port number.  */struct in_addr sin_addr;		/* Internet address.  *//* Pad to size of `struct sockaddr'.  */unsigned char sin_zero[sizeof (struct sockaddr)- __SOCKADDR_COMMON_SIZE- sizeof (in_port_t)- sizeof (struct in_addr)];};

其他结构:

typedef uint16_t in_port_t;typedef uint32_t in_addr_t;
struct in_addr{in_addr_t s_addr;};

in_addr 用来表示一个 IPv4 的 IP 地址. 其实就是一个 32 位的整数;

socket编程常用API
// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)
int socket(int domain, int type, int protocol);
// 绑定端口号 (TCP/UDP, 服务器)
int bind(int socket, const struct sockaddr *address, socklen_t address_len);
// 开始监听 socket (TCP, 服务器)
int listen(int socket, int backlog);
// 接收请求 (TCP, 服务器)
int accept(int socket, struct sockaddr* address, socklen_t* address_len);
// 建立连接 (TCP, 客户端)
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
http://www.dtcms.com/a/410350.html

相关文章:

  • 【音频】SIP服务器Yate搭建
  • 贵阳网站建设宏思锐达网站挂服务器后图片不显示
  • @tanstack/react-query:React 服务器状态管理与数据同步解决方案
  • RCNN系列边界框回归损失函数
  • 郑州专业网站制作建设python基础教程雪峰
  • Go基础:文件与文件夹操作详解
  • 鸿蒙:侧边栏显示与隐藏
  • 【开题答辩实录分享】以《基于爬虫的娱乐新闻采集系统设计与实现》为例进行答辩实录分享
  • BMAD方法论与自动化工具的协同演进:重塑Go语言微服务的技术债务
  • 月匣 - 百度推出的AI情感陪伴与剧情互动应用
  • dw网站建设教程网站建设费税率
  • 网站样版风格排版WordPress超级链接不跳转
  • Redis 五大核心数据结构知识点梳理
  • 微信小程序学习(一)
  • 零售企业档案检索慢?档案管理系统解决档案管理痛点
  • Docker 全阶段学习指南
  • Arbess从入门到实战(3) - 使用Arbess+GitLab实现Vue.js项目自动化部署
  • 智慧停车大屏数据分析与设计文档
  • 网站建设商家注册免费
  • 做网站后台系统的规范个人小程序商城
  • Linux 进程程序替换
  • 铜钟音乐前端技术解析
  • Flutter 运行IOS真机,提示无法打开“****”
  • Windows配置C/C++环境:MinGW+Vscode
  • Docker安装(Centos/Ubuntu/UOS)
  • 自动化运维利器:MCP Server + 阿里云
  • 常州公司建站模板网站怎么做定位功能
  • 网站弹窗代码网络游戏开发成本
  • Linux的网络基础
  • 福田网站建设课程考试wordpress页面链接404