【Linux网络编程】第二弹---Socket编程入门指南:从IP、端口号到传输层协议及编程接口全解析

个人主页: 熬夜学编程的小林

💗系列专栏: 【C语言详解】 【数据结构详解】【C++详解】【Linux系统编程】【Linux网络编程】

目录

1、Socket 编程预备

1.1、理解源 IP 和目的 IP 

1.2、认识端口号

1.2.1、端口号范围划分

1.2.2、理解 "端口号" 和 "进程 ID"

1.2.3、理解源端口号和目的端口号

1.2.4、理解 socket

1.3、传输层的典型代表

1.3.1、认识 TCP 协议

1.3.2、认识 UDP 协议

1.4、网络字节序

1.5、socket 编程接口

1.5.1、socket 常见 API

1.5.2、sockaddr 结构


1、Socket 编程预备

1.1、理解源 IP 和目的 IP 

  • IP 在网络中,用来标识主机的唯一性
  • 注意:后面我们会讲 IP 的分类,后面会详细阐述 IP 的特点

但是这里要思考一个问题:数据传输到主机是目的吗?

不是的因为数据是给人用的。比如:聊天是人在聊天,下载是人在下载,浏览网页是人在浏览?但是人是怎么看到聊天信息的呢?怎么执行下载任务呢?怎么浏览网页信息呢?通过启动的 qq,迅雷,浏览器。而启动的 qq,迅雷,浏览器都是进程。换句话说,进程是人在系统中的代表,只要把数据给进程,人就相当于就拿到了数据。

所以:数据传输到主机不是目的,而是手段。到达主机内部,在交给主机内的进程,才是目的。但是系统中,同时会存在非常多的进程,当数据到达目标主机之后,怎么转发给目标进程?

这就要在网络的背景下,在系统中,标识主机的唯一性

1.2、认识端口号

  • 端口号(port)是传输层协议的内容.
  • 端口号是一个 2 字节 16 位的整数;
  • 端口号用来标识一个进程, 告诉操作系统, 当前的这个数据要交给哪一个进程来处理;
  • IP 地址 + 端口号能够标识网络上的某一台主机的某一个进程;
  • 一个端口号只能被一个进程占用

1.2.1、端口号范围划分

  • 0 - 1023: 知名端口号, HTTP, FTP, SSH 等这些广为使用的应用层协议, 他们的端口号都是固定的.
  • 1024 - 65535: 操作系统动态分配的端口号. 客户端程序的端口号, 就是由操作系统从这个范围分配的. 

1.2.2、理解 "端口号" 和 "进程 ID"

我们之前在学习系统编程的时候, 学习了 pid 表示唯一一个进程; 此处我们的端口号也是唯一表示一个进程. 那么这两者之间是怎样的关系?

10086 例子

另外, 一个进程可以绑定多个端口号; 但是一个端口号不能被多个进程绑定;

  • 进程 ID 属于系统概念,技术上也具有唯一性,确实可以用来标识唯一的一个进程,但是这样做,会让系统进程管理和网络强耦合,实际设计的时候,并没有选择这样做。

1.2.3、理解源端口号和目的端口号

传输层协议(TCP 和 UDP)的数据段中有两个端口号, 分别叫做源端口号目的端口号.就是在描述 "数据是谁发的, 要发给谁";

1.2.4、理解 socket

  • 综上,IP 地址用来标识互联网中唯一的一台主机port 用来标识该主机上唯一的一个网络进程
  • IP+Port 就能表示互联网中唯一的一个进程
  • 所以,通信的时候,本质是两个互联网进程代表人来进行通信,{srcIp,srcPort,dstIp,dstPort}这样的 4 元组就能标识互联网中唯二的两个进程
  • 所以,网络通信的本质,也是进程间通信
  • 我们把 ip+port 叫做套接字 socket
socket
n.
(电源)插座;(电器上的)插口,插孔,管座;槽;窝;托座;臼;孔穴
vt.
把…装入插座;给…配插座

1.3、传输层的典型代表

  • 如果我们了解了系统,也了解了网络协议栈,我们就会清楚,传输层是属于内核的,那么我们要通过网络协议栈进行通信,必定调用的是传输层提供的系统调用,来进行的网络通信

1.3.1、认识 TCP 协议

此处我们先对 TCP(Transmission Control Protocol 传输控制协议)有一个直观的认识;后面我们再详细讨论 TCP 的一些细节问题.

  • 传输层协议
  • 有连接
  • 可靠传输
  • 面向字节流 

1.3.2、认识 UDP 协议

此处我们也是对 UDP(User Datagram Protocol 用户数据报协议)有一个直观的认识; 后面再详细讨论.

  • 传输层协议
  • 无连接
  • 不可靠传输
  • 面向数据报

注意:上面UDP的不可靠协议代表不能通信,只是相比于可靠协议更为简单,考虑的细节更少,但是也能正常通信!
因为我们暂时还没有深入了解 tcp、udp 协议,此处只做了解即可

1.4、网络字节序

我们已经知道,内存中的多字节数据相对于内存地址有大端和小端之分, 磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分, 网络数据流同样有大端小端之分. 那么如何定义网络数据流的地址呢?

  • 发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出;
  • 接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存;
  • 因此,网络数据流的地址应这样规定:先发出的数据是低地址,后发出的数据是高地址.
  • TCP/IP 协议规定,网络数据流应采用大端字节序,即低地址高字节.
  • 不管这台主机是大端机还是小端机, 都会按照这个 TCP/IP 规定的网络字节序来发送/接收数据;
  • 如果当前发送主机是小端, 就需要先将数据转成大端; 否则就忽略, 直接发送即可;

为使网络程序具有可移植性,使同样的 C 代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换。 

#include <arpa/inet.h>// 将32位无符号整数从主机字节顺序转换为网络字节顺序。
uint32_t htonl(uint32_t hostlong);// 将16位无符号整数从主机字节顺序转换为网络字节顺序。
uint16_t htons(uint16_t hostshort);// 将32位无符号整数从网络字节顺序转换为主机字节顺序。
uint32_t ntohl(uint32_t netlong);// 将16位无符号整数从网络字节顺序转换为主机字节顺序。
uint16_t ntohs(uint16_t netshort);

  • 这些函数名很好记,h 表示 host,n 表示 network,l 表示 32 位长整数,s 表示 16 位短整数
  • 例如 htonl 表示将 32 位的长整数从主机字节序转换为网络字节序,例如将 IP 地址转换后准备发送。
  • 如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回;
  • 如果主机是大端字节序,这些函数不做转换,将参数原封不动地返回。 

1.5、socket 编程接口

1.5.1、socket 常见 API

socket()

socket - 创建一个套接字(socket)(TCP/UDP, 客户端 + 服务器)

#include <sys/types.h>         
#include <sys/socket.h>int socket(int domain, int type, int protocol);

参数

  1. domain:指定协议族(Protocol Family),也称为协议域。常用的协议族有:

    • AF_INETIPv4 Internet协议
    • AF_INET6:IPv6 Internet协议。
    • AF_LOCAL(或AF_UNIX):本地通信协议,用于同一台机器上的进程间通信。
    • 其他协议族还包括AF_ROUTEAF_AX25AF_ATMPVC等,但它们在网络通信中较为少见。
  2. type:指定套接字类型(Socket Type)。常见的套接字类型有:

    • SOCK_STREAM流式套接字,提供序列化的、可靠的、双向连接的字节流。通常使用TCP协议。
    • SOCK_DGRAM数据报套接字,支持无连接的、不可靠的和使用固定大小(通常很小)缓冲区的数据报服务。通常使用UDP协议。
    • SOCK_RAW:原始套接字,允许对较低层协议(如IP、ICMP)直接访问。常用于检验新的协议实现或访问现有服务中配置的新设备。
    • 其他类型还包括SOCK_SEQPACKETSOCK_RDMSOCK_PACKET等,但它们在特定场景下使用。
  3. protocol指定某个协议的特定类型。通常,当protocol参数为0时,系统会自动选择type类型对应的默认协议。但有些协议可能有多种特定的类型,此时需要设置这个参数来选择特定的类型。

返回值

  • 如果socket函数调用成功,它会返回一个非负的文件描述符(File Descriptor),该描述符唯一标识一个套接字。
  • 如果调用失败,socket函数会返回-1,并设置errno来指示错误原因

bind()

将一个套接字(socket)与一个特定的IP地址和端口号绑定在一起。

#include <sys/types.h>          
#include <sys/socket.h>int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

参数

  • sockfd:要绑定的套接字的文件描述符
  • addr:指向包含地址信息的结构体的指针。通常使用struct sockaddr_in表示IPv4地址,或struct sockaddr_in6表示IPv6地址。
  • addrlen:地址结构体的大小

返回值

  • 如果bind函数调用成功,返回0。
  • 如果调用失败,返回-1,并设置errno来指示错误原因
// 接收请求 (TCP, 服务器)
int accept(int socket, struct sockaddr* address,
socklen_t* address_len);
// 建立连接 (TCP, 客户端)
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);

1.5.2、sockaddr 结构

socket API 是一层抽象的网络编程接口,适用于各种底层网络协议,如 IPv4、IPv6,以及后面要讲的 UNIX Domain Socket. 然而, 各种网络协议的地址格式并不相同.

  • IPv4 和 IPv6 的地址格式定义在 netinet/in.h 中,IPv4 地址用 sockaddr_in 结构体表示,包括 16 位地址类型, 16 位端口号和 32 位 IP 地址.
  • IPv4、IPv6 地址类型分别定义为常数 AF_INET、AF_INET6. 这样,只要取得某种 sockaddr 结构体的首地址,不需要知道具体是哪种类型的 sockaddr 结构体,就可以根据地址类型字段确定结构体中的内容.
  • socket API 可以都用 struct sockaddr *类型表示, 在使用的时候需要强制转化成sockaddr_in; 这样的好处是程序的通用性, 可以接收 IPv4, IPv6, 以及 UNIX Domain Socket 各种类型的 sockaddr 结构体指针做为参数;

sockaddr 结构

/* Structure describing a generic socket address.  */
struct sockaddr{__SOCKADDR_COMMON (sa_);	/* Common data: address family and length.  */char sa_data[14];		/* Address data.  */};

sockaddr_in 结构

/* Structure describing an Internet socket address.  */
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)];};

虽然 socket api 的接口是 sockaddr, 但是我们真正在基于 IPv4 编程时, 使用的数据结构是 sockaddr_in; 这个结构里主要有三部分信息: 地址类型, 端口号, IP 地址

in_addr 结构

/* Internet address.  */
typedef uint32_t in_addr_t;
struct in_addr{in_addr_t s_addr;};

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/62331.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何借助AI生成PPT,让创作轻松又高效

PPT是现代职场中不可或缺的表达工具&#xff0c;但同时也可能是令人抓狂的时间杀手。几页幻灯片的制作&#xff0c;常常需要花费数小时调整字体、配色与排版。AI的飞速发展为我们带来了革新——AI生成PPT的技术不仅让制作流程大大简化&#xff0c;还重新定义了效率与创意的关系…

基于时间维度优化“开源 AI 智能名片 S2B2C 商城小程序”运营策略:提升触达与转化效能

摘要&#xff1a; 随着数字化商业生态的蓬勃发展&#xff0c;“开源 AI 智能名片 S2B2C 商城小程序”融合前沿技术与创新商业模式&#xff0c;为企业营销与业务拓展带来新机遇。本文聚焦于用户时间场景维度&#xff0c;深入剖析如何依据不同时段用户行为特征&#xff0c;精准适…

【消息序列】详解(8):探秘物联网中设备广播服务

目录 一、概述 1.1. 定义与特点 1.2. 工作原理 1.3. 应用场景 1.4. 技术优势 二、截断寻呼&#xff08;Truncated Page&#xff09;流程 2.1. 截断寻呼的流程 2.2. 示例代码 2.3. 注意事项 三、无连接外围广播过程 3.1. 设备 A 启动无连接外围设备广播 3.2. 示例代…

vue3的prop

- 父组件需要传多个值给子组件 把值放对象&#xff0c;通过v-bind传整个对象 父组件 <script setup> import BlogPost from ./BlogPost.vue import { reactive } from vue; // 要传给子组件的所有值&#xff0c;用reactive包了该对象后&#xff0c;父组件的值变了&#…

Ubuntu下的Doxygen+VScode实现C/C++接口文档自动生成

Ubuntu下的DoxygenVScode实现C/C接口文档自动生成 1、 Doxygen简介 Doxygen 是一个由 C 编写的、开源的、跨平台的文档生成系统。最初主要用于生成 C 库的 API 文档&#xff0c;但目前又添加了对 C、C#、Java、Python、Fortran、PHP 等语言的支持。其从源代码中提取注释&…

uniapp强制修改radio-group内单选组件的状态方法

在uniapp开发中&#xff0c;需要在radio-group内部切换时做判断&#xff0c;提醒客户是否要变换radio的值&#xff0c;但是大家知道radio是单选组件&#xff0c;往往你点击后&#xff0c;是不能再修改状态的&#xff0c;就算你在点击后做判断&#xff0c;修改current的值&#…

数据结构-最短路径问题

一.问题分类 二.无权图单源最短路算法 dist[]数组记录的是个个顶点到源点的距离这个数组的下标表示顶点 源点到自己的距离是0,dist[s]0 path[]数组记录的是这个顶点的前驱&#xff0c;可以同过这个数组找到源点到个个顶点的距离 代码如下 void Unweighted(MGraph Graph, Ver…

Vue.js 实现用户注册功能

在本篇博客中&#xff0c;我们将通过一个简单的例子来展示如何使用 Vue.js 来实现一个用户注册功能。我们将创建一个包含用户名、邮箱和密码输入的表单&#xff0c;并在用户点击“创建账号”按钮时进行简单的验证。 完整代码 <!DOCTYPE html> <html lang"en&q…

【Java 学习】面向程序的三大特性:封装、继承、多态

引言 1. 封装1.1 什么是封装呢&#xff1f;1.2 访问限定符1.3 使用封装 2. 继承2.1 为什么要有继承&#xff1f;2.2 继承的概念2.3 继承的语法2.4 访问父类成员2.4.1 子类中访问父类成员的变量2.4.2 访问父类的成员方法 2.5 super关键字2.6 子类的构造方法 3. 多态3.1 多态的概…

impala入门与实践

1.impala基本介绍 impala是cloudera提供的一款高效率的sql查询工具&#xff0c;提供实时的查询效果&#xff0c;官方测试性能比hive快10到100倍&#xff0c;其sql查询比sparkSQL还要更加快速&#xff0c;号称是当前大数据领域最快的查询sql工具。impala是参照谷歌的新三篇论文…

结构方程模型(SEM)入门到精通:lavaan VS piecewiseSEM、全局估计/局域估计;潜变量分析、复合变量分析、贝叶斯SEM在生态学领域应用

目录 第一章 夯实基础 R/Rstudio简介及入门 第二章 结构方程模型&#xff08;SEM&#xff09;介绍 第三章 R语言SEM分析入门&#xff1a;lavaan VS piecewiseSEM 第四章 SEM全局估计&#xff08;lavaan&#xff09;在生态学领域高阶应用 第五章 SEM潜变量分析在生态学领域…

小米PC电脑手机互联互通,小米妙享,小米电脑管家,老款小米笔记本怎么使用,其他品牌笔记本怎么使用,一分钟教会你

说在前面 之前我们体验过妙享中心&#xff0c;里面就有互联互通的全部能力&#xff0c;现在有了小米电脑管家&#xff0c;老款的笔记本竟然用不了&#xff0c;也可以理解&#xff0c;毕竟老款笔记本做系统研发的时候没有预留适配的文件补丁&#xff0c;至于其他品牌的winPC小米…

python爬虫案例——猫眼电影数据抓取之字体解密,多套字体文件解密方法(20)

文章目录 1、任务目标2、网站分析3、代码编写1、任务目标 目标网站:猫眼电影(https://www.maoyan.com/films?showType=2) 要求:抓取该网站下,所有即将上映电影的预约人数,保证能够获取到实时更新的内容;如下: 2、网站分析 进入目标网站,打开开发者模式,经过分析,我…

一分钟食用前端测试框架Jest

安装 其实食用Jest是很简单的,我们只需要安装Jest即可 npm install --save-dev jestyarn add --dev jestpnpm add --save-dev jest ESmodule 本身来说,Jest是不支持Esmodule的,他支持CommonJS,我们需要Babel改一下 npm i --save-dev babel-jest babel/core babel/preset-env …

从 App Search 到 Elasticsearch — 挖掘搜索的未来

作者&#xff1a;来自 Elastic Nick Chow App Search 将在 9.0 版本中停用&#xff0c;但 Elasticsearch 拥有你构建强大的 AI 搜索体验所需的一切。以下是你需要了解的内容。 生成式人工智能的最新进展正在改变用户行为&#xff0c;激励开发人员创造更具活力、更直观、更引人入…

若依框架部署在网站一个子目录下(/admin)问题(

部署在子目录下首先修改vue.config.js文件&#xff1a; 问题一&#xff1a;登陆之后跳转到了404页面问题&#xff0c;解决办法如下&#xff1a; src/router/index.js 把404页面直接变成了首页&#xff08;大佬有啥优雅的解决办法求告知&#xff09; 问题二&#xff1a;退出登录…

【贪心算法第六弹——334.递增的三元子序列(easy)】

目录 1.题目解析 题目来源 测试用例 2.算法原理 3.实战代码 代码解析 本题属于最长递增子序列的简化版本&#xff0c;只需要判断能不能组成三位的递增子序列即可&#xff0c;建议先去看博主的另一篇博客可以更好的理解本篇博客&#xff1a;300.最长递增子序列 1.题目解析…

《TCP/IP网络编程》学习笔记 | Chapter 16:关于 I/O 流分离的其他内容

《TCP/IP网络编程》学习笔记 | Chapter 16&#xff1a;关于 I/O 流分离的其他内容 《TCP/IP网络编程》学习笔记 | Chapter 16&#xff1a;关于 I/O 流分离的其他内容分离 I/O 流2 次 I/O 流分离分离「流」的好处「流」分离带来的 EOF 问题 文件描述符的的复制和半关闭终止「流」…

LeetCode数组题

参考链接 代码随想录 讲解视频链接 数组题 1、(两数之和)给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。你可以假设每种输入只会对应一个答案&#xff0c;并且你不能使用…

Unity-Lightmap入门篇

&#xff1a;&#xff1a;这是一个实战文章&#xff0c;并没有知识分享&#xff0c;或理论知识&#xff1b;完全没有 关键字&#xff1a; “lightmap","全局光照”&#xff0c;“light Probe" (会混合一些中英文搜索&#xff0c;或者全英文搜索&#xff09; …