计算机网络套接字知识(非常详细)从零基础入门到精通

news2024/9/21 0:48:15

本节重点

  • 认识IP地址, 端口号, 网络字节序等网络编程中的基本概念;

  • 学习socket api的基本用法;

一、预备知识

1.理解源IP地址和目的IP地址

⭐在IP数据包头部中,有两个IP地址,分别叫做源IP地址和目的IP地址。

思考: 我们光有IP地址就可以完成通信了嘛?想象一下发qq消息的例子,有了IP地址能够把消息发送到对方的机器上,但是还需要有一个其他的标识来区分出,这个数据要给哪个程序进行解析,此时就需要我们的目的IP地址。

2.认识端口号

在进行网络通信的时候,是不是我们的两台机器在进行通信呢?本质是应用层在通信

几乎任何层的协议,都要在报头中提供,决定将自己的有效载荷交付给上层的哪一个协议的能力,怎么做到的呢?端口号(port)是传输层协议的内容.

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

3.理解 "端口号" 和 "进程ID"

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

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

4.理解源端口号和目的端口号

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

socket通信本质上就是两个进程之间在进行通信,只不过这里是跨网络的进程间通信。比如看QQ和刷抖音的动作,实际就是手机上的QQ进程和抖音进程在和对端服务器主机上的QQ服务进程和抖音服务进程之间在进行通信。因此进程间通信的方式除了管道、消息队列、信号量、共享内存等方式外,还有套接字,只不过前者是不跨网络的,而后者是跨网络的。

⭐理解socket这个名字

socket在英文上有“插座”的意思,插座上有不同规格的插孔,我们将插头插入到对应的插孔当中就能够实现电流的传输。在进行网络通信时,客户端就相当于插头,服务端就相当于一个插座,但服务端上可能会有多个不同的服务进程(多个插孔),因此当我们在访问服务时需要指明服务进程的端口号(对应规格的插孔),才能享受对应服务进程的服务。

5.认识TCP协议和UDP协议

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

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

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

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

TCP协议是一种可靠的传输协议,使用TCP协议能够在一定程度上保证数据传输时的可靠性,而UDP协议是一种不可靠的传输协议,UDP协议的存在有什么意义?

首先,可靠是需要我们做更多的工作的,TCP协议虽然是一种可靠的传输协议,但这一定意味着TCP协议在底层需要做更多的工作,因此TCP协议底层的实现是比较复杂的,我们不能只看到TCP协议面向连接可靠这一个特点,我们也要能看到TCP协议对应的缺点。同样的,UDP协议虽然是一种不可靠的传输协议,但这一定意味着UDP协议在底层不需要做过多的工作,因此UDP协议底层的实现一定比TCP协议要简单,UDP协议虽然不可靠,但是它能够快速的将数据发送给对方,虽然在数据在传输的过程中可能会出错。

6.网络字节序

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

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

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

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

二、socket编程接口

1.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);

2.sockaddr结构

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

为什么没有用void*代替struct sockaddr*类型?

我们可以将这些函数的struct sockaddr*参数类型改为void*,此时在函数内部也可以直接指定提取头部的16个比特位进行识别,最终也能够判断是需要进行网络通信还是本地通信,那为什么还要设计出sockaddr这样的结构呢?实际在设计这一套网络接口的时候C语言还不支持void*,于是就设计出了sockaddr这样的解决方案。并且在C语言支持了void*之后也没有将它改回来,因为这些接口是系统接口,系统接口是所有上层软件接口的基石,系统接口是不能轻易更改的,否则引发的后果是不可想的,这也就是为什么现在依旧保留sockaddr结构的原因。

  • Pv4和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 结构

sockaddr_in 结构

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

这里使用了我们的"##",我们来回忆一下它的用法

所以上面定义的宏传入的参数是sin_,然后宏里面使用了"##"拼接family,这样就看到了我们的套接字的域。

⭐in_addr结构

可以看到,struct sockaddr_in当中的成员如下:

  • sin_family:表示协议家族。
  • sin_port:表示端口号,是一个16位的整数。
  • sin_addr:表示IP地址,是一个32位的整数。

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

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

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

相关文章

spring boot 集成mongodb

引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId><version>2.2.0.RELEASE</version></dependency>配置db: spring:data:mongodb:host: 127.0.…

【C++高阶(一)】继承

目录 一、继承的概念 1.继承的基本概念 2.继承的定义和语法 3.继承基类成员访问方式的变化 ​编辑 4.总结 二、基类和派生类对象赋值转换 三、继承中的作用域 四、派生类的默认成员函数 1.派生类中的默认构造函数 2.派生类中的拷贝构造函数 3.派生类中的移动构造函数…

Kubeadm安装部署k8s集群、踩坑日常

背景 ​ Docker是一个非常流行的容器化平台&#xff0c;它可以让我们方便构建、打包、发布和运行容器化应用程序。但是&#xff0c;在生产环境中&#xff0c;我们可能需要处理成百上千个容器&#xff0c;需要更好的管理这些容器&#xff0c;这就是Kubernetes(K8S)的用武之地。…

vue15:记事本vue指令案例

效果图&#xff1a; vue指令 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>帅临记事本</…

prometheusgrafananode_export搭建监控平台

一、环境要求 1、docker安装docker环境 2、docker安装prometheus 3、docker安装grafana 4、node-exportor(安装在被测服务器上) 5、我的服务器是Ubuntu 二、docker 安装prometheus 1、下载Prometheus镜像 docker pull prom/prometheus 2、检查端口是否被占用 安装netstat命…

24款奔驰S450升级原厂后排娱乐系统 主动氛围灯有哪些功能

24款奔驰S400豪华升级原厂主动氛围灯与后排娱乐系统&#xff1a;画蛇添足还是锦上添花&#xff1f; 在当今汽车市场竞争激烈的环境下&#xff0c;汽车制造商们为了满足消费者的多元化需求&#xff0c;不断推出各种升级配置和豪华版本。24款奔驰S400豪华版作为奔驰S级的一款重要…

碌时刻必备!微信自动回复让你告别消息堆积

在忙碌的时候&#xff0c;我们往往会面临消息堆积如山的情况。无法及时回复消息不仅容易造成交流障碍&#xff0c;还可能错过重要的机会。 但是现在&#xff0c;有一个神奇的工具——个微管理系统&#xff0c;可以帮助我们轻松应对这个问题 &#xff0c;实现微信自动回复。 首…

AIGC-风格迁移-style Injection in Diffusion-CVPR2024HighLight-论文精度

Style Injection in Diffusion: A Training-free Approach for Adapting Large-scale Diffusion Models for Style Transfer-CVPR2024HighLight 代码&#xff1a;https://github.com/jiwoogit/StyleID 论文&#xff1a;https://jiwoogit.github.io/StyleID_site/ 为了解决风格迁…

WXSS模板样式-全局样式和局部样式

一、WXSS 1.WXSS WXSS(WeiXin Style Sheets)是一套样式语言&#xff0c;用于美化WXML的组件样式&#xff0c;类似于网页开发中的CSS 2.WXSS和CSS的关系 WXSS具有CSS大部分特性&#xff0c;同时&#xff0c;WXSS还对CSS进行了扩充以及修改&#xff0c;以适应微信小程序的开发…

详解 Spring MVC(Spring MVC 简介)

什么是 Spring MVC&#xff1f; Spring MVC 是 Spring 框架提供的一个基于 MVC 模式的轻量级 Web 框架&#xff0c;是 Spring 为表示层开发提供的一整套完整的解决方案&#xff0c;Spring MVC 使用了 MVC 架构模式&#xff0c;将 Web 层职责解耦&#xff0c;基于请求驱动模型&…

26计算机操作系统408考研-操作系统进程与线程篇章(三)

操作系统进程与线程篇章 ` 文章目录 操作系统进程与线程篇章前言一、进程概念进程控制块进程创建进程终止进程的阻塞和唤醒进程唤醒进程挂起和激活线程多线程线程实现与线程模型总结互斥和同步并发原理硬件同步信号量机制信号量的应用管程经典同步问题消息传递前言 一、进程概…

Qt 科目一考试系统(有源码)

项目源码和资源&#xff1a;科目一考试系统: qt实现科目一考试系统 一.项目概述 该项目是一个基于Qt框架开发的在线考试系统&#xff0c;主要实现了考试题目的随机抽取、考试时间限制、成绩统计等功能。用户可以通过界面操作进行考试&#xff0c;并查看自己的考试成绩。 二.技…

清理安卓手机广告

保存脚本另存为 Fuck_AD.sh&#xff0c;在手机执行后体验效果。 echo ""echo " " echo " - 开始执行清理广告库文件" sleep 3files(/data/app/*/*/lib/arm64/libpangleflipped.so/data/app/*/*/lib/arm64/libzeus_direct_dex.so/data/app/*/*/l…

力扣--哈希表13.罗马数字转整数

首先我们可以知道&#xff0c;一个整数&#xff0c;最多由2个罗马数字组成。 思路分析 这个方法能够正确将罗马数字转换为阿拉伯数字的原因在于它遵循了罗马数字的规则&#xff0c;并且对这些规则进行了正确的编码和处理。 罗马数字规则 罗马数字由以下字符组成&#xff1a…

第八届能源、环境与材料科学国际学术会议(EEMS 2024)

文章目录 一、重要信息二、大会简介三、委员会四、征稿主题五、论文出版六、会议议程七、出版信息八、征稿编辑 一、重要信息 会议官网&#xff1a;http://ic-eems.com主办方&#xff1a;常州大学大会时间&#xff1a;2024年06月7-9日大会地点&#xff1a;新加坡 Holiday Inn …

langchian进阶二:LCEL表达式,轻松进行chain的组装

LangChain表达式语言-LCEL&#xff0c;是一种声明式的方式&#xff0c;可以轻松地将链条组合在一起。 你会在这些情况下使用到LCEL表达式: 流式支持 当你用LCEL构建你的链时&#xff0c;你可以得到最佳的首次到令牌的时间(输出的第一块内容出来之前的时间)。对于一些链&#…

C语言.数据结构.顺序表

1.顺序表的概念及结构 1.1线性表 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串… 线性表在逻辑上是线性结构&#xff0c;…

创建FreeRTOS工程

创建STM32CubeMX工程 配置时钟 配置FreeRTOS 生成Keil MDK的工程 打开工程 结尾 这就是我们用STM32CubeMX创建的最基本的一个FreeRTOS的工程。可以看到&#xff0c;这个与我们使用stm32开发的裸机程序有相同的地方&#xff0c;也有不同的地方&#xff0c;我们可以发现&am…

Redis 哨兵机制的工作原理——Java全栈知识(22)

Redis 哨兵机制的工作原理 在之前的文章我们讲到了 Redis 的三种集群架构&#xff1a;跳转文章&#xff1a;Redis集群模式 接下来我们详细讲哨兵机制的作用以及实现原理 以下是 Redis 哨兵的结构图 1、Redis 哨兵的作用 哨兵的作用如下&#xff1a; 1、监控&#xff0c;2、…

Mysql基础(七)DQL之select 语句(二)

一 select 语句续 WHERE子句后面跟着的是一个或多个条件,用于指定需要检索的行COUNT(): 多少条数据 where 11 和 count(1) 与 count(*) count(1)、count(*)和count(指定字段)之间的区别 ① order by 排序 mysql 之数据排序扩展 1、使用 order by 语句来实现排序2、排序可…