【计算机网络】socket编程基础

文章目录

  • 1. 源IP地址和目的IP地址
  • 2. 理解MAC地址和目的MAC地址
  • 3. 理解源端口号和目的端口号
  • 4. PORT与PID
  • 5. 认识TCP协议和UDP协议
  • 6. 网络字节序
  • 7. socket编程接口
    • 7.1 socket常见API
    • 7.2 sockaddr结构

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

因特网上的每台计算机都有一个唯一的IP地址,如果一台主机上的数据要传输到另一台主机,那么对端主机的IP地址就应该作为该数据传输时的目的IP地址。但仅仅知道目的IP地址是不够的,当对端主机收到数据后,对端还需要对该主机作出相应,因此对端主机也需要发送数据给该主机,此时对端主机就需要知道该主机的IP地址。因此一个传输的数据中应该涵盖其IP地址和目的IP地址,目的IP地址表明该数据传输的目的,源IP地址作为对端主机相应时的目的IP地址。

在数据传输之前,会先自顶向下贯穿网络贯穿数据协议栈完成数据的封装,其中在网络层封装的IP报头当中就涵盖了就涵盖了源IP地址和目的IP地址。

2. 理解MAC地址和目的MAC地址

大部分数据的传输都是跨局域网的,数据在传输过程中会经过若干个路由器,最终才能到达对端主机。
在这里插入图片描述
源MAC地址和目的MAC地址是包含在链路层的报头当中的,而MAC地址实际只在当前局域网内有效。因此当数据跨网络到达另一个局域网时,也就是数据到达路由器时,路由器会将该数据当中链路层的报头去掉,然后再封装一个报头,此时该数据的源MAC地址和目的MAC地址就发生了变化。

因此数据在传输的过程中是有两套地址:

  1. 一套是源IP地址和目的IP地址,这两个地址在数据传输过程中基本是不会发生变化的(存在一些特殊情况,比如使用了NET技术,其源IP地址会发生变化,但是目的IP地址不会发生变化)
  2. 另一套就是源MAC地址和目的MAC地址,这两个地址是会发生变化的,因为在数据传输的过程中会路由器会进行解包和重新封装。

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

套接字通信的本质

首先我们需要理解的是,两个主机之间进行通信,不仅仅是为了将数据发给对端主机,而是为了访问对端主机上的某个服务。比如我们在使用百度搜索引擎时,我们不仅仅将我们的请求发给对端服务器,而是想访问对端服务器上部署的百度相关的搜索服务。

我们可以通过IP地址和MAC地址将数据发给对端主机,但实际上我们是要发给对端数据上的某个进程,此外,数据的发送者也不是主机,而是主机上的某个进程。比如,当我们用浏览器访问网站时,实际也就是浏览器进程向对端服务器进程发起请求。
在这里插入图片描述
也就是说,套接字通信的本质就是两个进程之间在进行通信,只不过这里是跨网络的进程间通信。比如我们刷抖音的时候,其实就是我们手机上的抖音进程在于对端服务器主机上的抖音服务器进程在进行通信。

因此进程间通信的方式除了管道,共享内存,消息队列,信号量之外,还有套接字,只不过套接字是跨网络的。

认识端口号

实际在两台主机上,可能会存在许多进行网络通信的进程,当数据发送到该主机之后,需要将数据交给指定的进程。而当进程处理完数据之后还要对发送端进行相应,因此对端主机也需要知道是发送端上哪一个进程向它发起请求。

端口号(port)的作用就是标识一台主机上的一个进程。

  • 端口号是传输层协议的内容
  • 端口号是一个2字节16位的整数
  • 端口号用来表示一个进程,告诉操作系统,当前这个数据要交给哪个进程处理
  • 一个端口号只能被一个进程占有

由于IP地址可以标识公网内的某一台主机,而端口号又可以标识主机上的某一个进程,因此用IP地址+端口号就可以标识网络上某一台主机的某一进程了。

当数据在传输层进行封装时,就会添加上对应源端口号和目的端口号的信息,在网络层又会添加上对应源IP地址和目的IP地址,这样一来,通过源端口号和源IP地址就能在网络上标识发送数据的进程,通过目的端口号和目的ID地址就可以在网络上标识接收数据的进程,这就实现了跨网络的进程间通信。

注意:因为端口号是属于某台主机的,所以端口号可以在两台不同的主机当中重复,但是在同一台主机上进行网络通信的端口号不能重复。此外,一个进程可以绑定多个端口号,但是一个端口号只能被一个进程绑定。

理解“套接字”这个名字

套接字源自于单词socket,套接字编程实际上就是socket编程。socket在英文上也有插座的意思,在进行网络通信的时候,客户端就相当于接口,服务端就相当于一个插座,但服务端上可能会有许多不同的服务进程(多个插孔),因此当我们在访问服务时需要指明服务进程端口号(对应规则的插孔),才能得到对应服务进程的服务。

而套接字,我们也可以姑且理解为一套用于连接的文字。

4. PORT与PID

端口号(port)的作用是表示主机上的某个进程,进程PID的作用也是表示主机上的某个进程,那为什么在进行网络通信的时候不直接使用PID来代替port呢?

进程PID是用来表示系统内进程的唯一性的,属于系统级别的概念。而端口号是在网络通信时标识进程的唯一性的,属于网络级别的概念。

每个人都有自己的身份证号,但是为了方便管理,到了学习会有学号,到了公司会有工号。网络通信使用port同理。

且在网络中使用port,在系统中使用PID,可以使网络和系统很好地解耦。

底层是如何通过port找到进程的? 实际底层采用哈希的方式建立了端口号和进程PID或PCB之间的映射关系,当底层拿到端口号时就可以直接执行对应的哈希算法,然后就能找到该端口号对应的进程。

5. 认识TCP协议和UDP协议

当我们使用系统调用接口实现网络数据通信时,不得不面对的协议层就是传输层,而传输层最经典的两种协议就是TCP协议和UDP协议。

TCP协议

TCP协议叫做传输控制协议(Transmission Control Protocol),TCP是一种面向连接的,可靠的,基于字节流的传输层控制协议。

TCP是面向连接的,如果两台主机之间要进行数据传输,必须先建立连接,在连接建立完成之后才可以进行数据传输。其次,TCP是保证可靠的协议,数据在传输过程中如果出现了丢包、乱序等情况,TCP都有对应的解决方案。

UDP协议

UDP协议叫做用户数据报协议(User Datagram Protocol),UDP是一种无需建立连接的、不可靠的、面向数据报的传输层通信协议。

使用UDP协议进行通信时无需建立连接,如果两台主机之间想要进行数据传输,那么直接将数据发给对端主机就行了,但这也就意味着UDP协议是不可靠的,数据在传输过程中如果出现了丢包、乱序等情况,UDP协议本身是不知道的。

既然UDP协议是不可靠的,那为什么还要有UDP协议的存在?

TCP协议是一种可靠的传输协议,使用TCP协议可以保证数据传输时的可靠性,而UDP协议是一种不可靠的传输协议,它的存在有什么意义呢?

首先,可靠是需要我们更多的工作的,TCP协议虽然是一种可靠的传输协议,但这意味着TCP协议在底层一定要做更多的工作,因此TCP协议底层的实现是比较复杂的,我们不能只看到TCP协议面向连接这个优点。还要看到TCP协议对应的缺点。

同样的,UDP协议虽然是一种不可靠的传输协议,但这一定意味着UDP协议在底层不需要做过多的工作,因此UDP协议底层的实现一定比TCP协议要简单的多,UDP协议虽然不可靠,但是它能把数据快速地发给对方,虽然数据在传输的过程中可能会出错。

编写网络通信代码时具体采用TCP协议还是UDP协议,完全取决于上层的应用场景。如果应用场景严格要求数据在传输过程中的可靠性,我们就必须采用TCP协议,如果应用场景允许数据在传输出现少量丢包,那么我们肯定优先选择UDP协议,因为UDP协议足够简单。

一些网站在设计网络通信算法时,会同时采用TCP协议和UDP协议,当网络流畅时就使用UDP协议进行数据传输,当网络不好时就使用TCP协议进行数据传输,此时就可以动态地调整后台通信算法。

6. 网络字节序

网络中的大小端问题

计算机在存储数据时是有大小端的概念的:

  • 大端模式:数据的高字节内容保存在内存的低地址处,数据的低字节内容保存在内存的高地址处。
  • 小端模式:数据的高字节内容保存在内存的高地址处,数据的低字节内容保存在内存的低地址处。

如果编写的程序只在本地机器上运行,那么是不需要考虑大小端问题的,因为同一台机器上采用的存储方式都是一样的,要么采用大端存储模式,要么采用小端存储模式。但如果设计网络通信,那就必须考虑大小端的问题,否则对端主机识别出来的数据可能与发送端想要发送的数据是不一致的。

例如,现在两台主机在进行网络通信,其中发送端是小端机,而接收端是大端机。发送端将发送缓冲区内的数据按内存地址从低到高的顺序发出后,接收端从网络中获取数据一次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存的。
在这里插入图片描述
但由于发送端和接收端采用的分别是小端存储和大端存储,此时对于内存地址从低到高为 44332211 的序列,发送端按小端的方式识别出来的是 0x11223344,但是接收端按大端的方式识别的是 0x44332211,此时接收端接收到的数据就与发送端原本想要发送的数据就不一样了,这就是由于大小端的偏差导致数据识别出现了错误。

由于我们不能保证通信双方存储数据的方式是一样的,因此网络当中传输的数据必须考虑大小端问题。因此TCP/IP协议规定,网络数据流采用大端字节序,即低地址高字节。无论是大端机还是小端机,都必须按照TCP/IP协议当中规定的网络字节序来发送和接收数据。

  • 如果发送端是小端,需要先将数据转成大端,然后再发送到网络当中
  • 如果发送端是大端,则可以直接进行发送
  • 如果接收端是小端,需要先将数据转换成小端后再进行数据识别
  • 如果接收端是大端,则可以直接进行数据识别。

主机字节序和网络字节序直接的转换接口

为了使网络程序具有可移植性,使同样的C代码在大端和小端机器上编译后都能正常运行,系统提供了四个函数,可以通过调用以下库函数实现网络字节序和主机字节序直之间的转换:
在这里插入图片描述

  • 函数名中的h表示host,n表示network,l表示32位长整数,s表示16位短整数
  • 例如htonl表示将32位长整数从主机字节序转换为网络字节序
  • 如果主机是小端字节序,则这些函数将参数做相应的大小端转换然后返回
  • 如果主机是大端字节序,则这些函数不做任何转换,将参数原封不动地返回

7. socket编程接口

7.1 socket常见API

创建套接字:(TCP/UDP,客户端+服务端)

在这里插入图片描述

绑定端口号:(TCP/UDP,服务器)

在这里插入图片描述

监听套接字:(TCP,服务器)

在这里插入图片描述

接收请求:(TCP,服务器)

在这里插入图片描述

建立连接:(TCP,客户端)

在这里插入图片描述

7.2 sockaddr结构

sockaddr结构的出现

套接字不仅支持跨网络的进程间通信,还支持本地的进程间通信(域间套接字)。在进行跨网络通信时我们需要传递的端口号和IP地址,而本地通信则不需要,因此套接字提供了sockaddr_in结构体和sockaddr_un结构体,其中sockaddr_in结构体是用于跨网络通信的,而sockaddr_un结构体是用于本地通信的。

为了让套接字的网络通信和本地通信能够使用同一套函数接口,于是就出现了sockaddr结构体,该结构体与sockaddr_in结构体和sockaddr_un的结构都不相同,但这三个结构体头部的16个比特位都是一样的,这个字段叫做协议家族。

在这里插入图片描述
此时当我们在传参时,就不用传入sockaddr_in或者sockaddr_un这样的结构体,而统一传入sockaddr这样的结构体。在设置参数时就可以通过设置协议家族这个字段,来表明我们是要进行网络通信还是本地通信,在这些API内部就可以提取sockaddr结构体的16位头部进行识别,进而得出我们是要进行网络通信还是本地通信,然后执行对应的操作。这样我们通过sockaddr结构,就将套接字网络通信和本地通信的参数类型实现了统一。

注意:实际我们在进行网络通信的时候,定义的还是sockaddr_in这样的结构体,只不过在传参时需要将该结构体的地址类型进行强转为==sockaddr*==罢了。

为什么不用 void* 代替 struct sockaddr* 类型呢

我们可以将这些函数接口形参的struct sockaddr参数改为void,此时在函数背部也可以直接提取头部的16个比特位进行识别,最终也能够判断是需要进行网络通信还是本地通信,那为什么还要设计出sockaddr这样的结构呢?

实际在设计这一套网络接口的时候C语言还不支持void* ,于是就设计出了sockaddr这样的解决方案。

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

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

相关文章

性能优化问题

提升首屏的加载速度,是前端性能优化中「最重要」的环节,这里笔者梳理出一些 常规且有效 的首屏优化建议 1、路由懒加载 SPA 项目,一个路由对应一个页面,如果不做处理,项目打包后,会把所有页面打包成一个文…

Android平台如何实现第三方模块编码后(H.264/H.265/AAC/PCMA/PCMU)数据实时预览播放

技术诉求 我们在做GB28181设备对接模块和RTMP直播推送模块的时候,遇到这样的技术需求,设备(如执法记录仪)侧除了采集传统的摄像头外,还需要对接比如大疆等第三方数据源,确保按照GB28181规范和RTMP协议规范…

【后端面经-Spring】Spring简介

【后端面经-Spring】Spring简介 1. Spring简介2. Spring模块3. Spring核心特性4. Spring的后续拓展面试模拟参考资料 1. Spring简介 Spring是为了简化java项目开发设计的一款设计层面开源框架,其设计目的就是为了“简化开发”。 它使用分层架构,解决业务…

[NLP]Huggingface模型/数据文件下载方法

问题描述 作为一名自然语言处理算法人员,hugging face开源的transformers包在日常的使用十分频繁。在使用过程中,每次使用新模型的时候都需要进行下载。如果训练用的服务器有网,那么可以通过调用from_pretrained方法直接下载模型。但是就本人…

React Dva项目中.roadhogrc.mock.js直接自动导入mock目录下所有文件方式

上文 React Dva项目中模仿网络请求数据方法 中,我们书写了Dva项目模拟后端数据的方式 但是 我们.roadhogrc.mock.js中的这个处理其实并不好用 我们还需要一个一个的引入 我们可以直接靠一段代码 import fs from fs; import path from path; const mock {} fs.re…

19. 删除链表的倒数第 N 个结点

题目介绍 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。 示例 1: 输入:head [1,2,3,4,5], n 2 输出:[1,2,3,5]示例 2: 输入:head [1], n 1 输出:[]示例 3&…

NLP(六十二)HuggingFace中的Datasets使用

Datasets库是HuggingFace生态系统中一个重要的数据集库,可用于轻松地访问和共享数据集,这些数据集是关于音频、计算机视觉、以及自然语言处理等领域。Datasets 库可以通过一行来加载一个数据集,并且可以使用 Hugging Face 强大的数据处理方法…

[Tools: tiny-cuda-nn] Linux安装

official repo: https://github.com/NVlabs/tiny-cuda-nn 该包可以显著提高NeRF训练速度,是Instant-NGP、Threestudio和NeRFstudio等框架中,必须使用的。 1. 命令行安装 最便捷的安装方式,如果安装失败考虑本地编译。 pip install ninja g…

区块链与加密货币在Web3中的融入及意义

Web3是指下一代互联网,也被称为去中心化互联网。它的核心理念是建立一个去中心化的经济和社会系统,使得个人和社区能够更加自治和自主,而不依赖于中心化的机构和权力。 在Web3中,区块链和加密货币是非常重要的技术和概念。区块链是…

1.前端入门

文章目录 一、基础认知1.1 认识网页:1.2 五大浏览器1.3 Web标准 总结 提示:以下是本篇文章正文内容,下面案例可供参考 一、基础认知 1.1 认识网页: 1.网页由哪些部分组成? 文字、图片、音频、视频、超链接。 2.我们…

【机器学习】异常检测

异常检测 假设你是一名飞机涡扇引擎工程师,你在每个引擎出厂之前都需要检测两个指标——启动震动幅度和温度,查看其是否正常。在此之前你已经积累了相当多合格的发动机的出厂检测数据,如下图所示 我们把上述的正常启动的数据集总结为 D a t…

Jmeter常见问题之URI异常

这篇文章介绍一下"http://"重复导致的URI异常问题,通常从浏览器地址栏复制url,直接粘贴到Jmeter的http请求的服务器地址中会默认带上“http://”,要将http://删除,只写IP地址,如下图: 否则&…

项目开启启动命令整合

启动RabbitMQ管理插件 1.启动 RabbitMQ 管理插件。 rabbitmq-plugins enable rabbitmq_management rabbitmq-server # 直接启动,如果关闭窗⼝或需要在该窗⼝使⽤其他命令时应⽤就会停⽌ rabbitmq-server -detached # 后台启动 rabbitmq-server start # 启⽤服务 rab…

16.喝水

喝水 html部分 <h1>Goal: 2 Liters</h1> <div class"cup cupbig"><div class"remained"><span id"liters">2L</span><small>Remained</small></div><div class"percentage&quo…

PHY芯片的使用(三)在linux下网络PHY的移植

1 前言 配置设备树请参考上一章。此次说明还是以裕太的YT8511芯片为例。 2 需要配置的文件及路径 a. 在 .. /drivers/net/phy 目录下添加 yt_phy.c 文件&#xff08;一般来说该驱动文件由厂家提供&#xff09;&#xff1b; b. 修改.. /drivers/net/phy 目录下的 Kconfig 文…

win10电脑便签常驻桌面怎么设置?

你是否曾经因为繁忙的工作而忘记了一些重要的事项&#xff1f;相信很多人都会回答&#xff1a;忘记过&#xff01;其实在快节奏的职场中&#xff0c;我们经常需要记录一些重要的信息&#xff0c;例如会议时间、约见客户时间、今天需要完成的工作任务等。而为了能够方便地记录和…

nodejs+vue+elementui学习交流和学习笔记分享系统

Node.js 是一个基于 Chrome JavaScript 运行时建立的一个平台。 前端技术&#xff1a;nodejsvueelementui,视图层其实质就是vue页面&#xff0c;通过编写vue页面从而展示在浏览器中&#xff0c;编写完成的vue页面要能够和控制器类进行交互&#xff0c;从而使得用户在点击网页进…

Spring Cloud Alibaba 集成 Skywalking 链路追踪

Spring Cloud Alibaba 集成 Skywalking 链路追踪 简介 skywalking 是一个国产开源框架&#xff0c;2015 年由吴晟开源 &#xff0c; 2017 年加入 Apache 孵化器。skywalking 是分布式系统的应用程序性能监视工具&#xff0c;专为微服务、云原生架构和基于容器&#xff08;Doc…

redis中使用bloomfilter的白名单功能解决缓存预热问题

一 缓存预热 1.1 缓存预热 将需要的数据提前缓存到缓存redis中&#xff0c;可以在服务启动时候&#xff0c;或者在使用前一天完成数据的同步等操作。保证后续能够正常使用。 1.2 解决办法PostConstruct注解初始化

【复习16-18天】【我们一起60天准备考研算法面试(大全)-第二十四天 24/60】

专注 效率 记忆 预习 笔记 复习 做题 欢迎观看我的博客&#xff0c;如有问题交流&#xff0c;欢迎评论区留言&#xff0c;一定尽快回复&#xff01;&#xff08;大家可以去看我的专栏&#xff0c;是所有文章的目录&#xff09;   文章字体风格&#xff1a; 红色文字表示&#…