Socket 编程原理

Socket 编程原理目录socket编程基本概念协议TCPUDPDNSICMPHTTPHTTPS编程流程socket函数socket编程基本概念socket编程即计算机网络编程,目的是使两台主机能够进行远程连接,既然要使两者产生联系,那么就要有至少一个信息发送端和一个信息接收端,因此形成了现在绝大多数socket编程都会用到的C/S架构(Client[客户端]/Server[服务端]),最典型的应用就是web服务器/客户端。在Unix/Linux中执行任何形式的I/O操作(比如网络连接)时,都是在读取

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

socket编程

基本概念

socket编程即计算机网络编程,目的是使两台主机能够进行远程连接,既然要使两者产生联系,那么就要有至少一个信息发送端和一个信息接收端,因此形成了现在绝大多数 socket 编程都会用到的 C/S 架构(Client[客户端]/Server[服务端]),最典型的应用就是 web服务器/客户端。
在 Unix/Linux 中执行任何形式的 I/O 操作(比如网络连接)时,都是在读取或写入一个文件描述符,而在 Windows 中则被称为文件句柄,其本质都是一个东西,但是 Windows系统会把 socket 当成一个网络连接,需要调用专门设计的数据传输函数。
socket (套接字)是一种抽象层,程序通过它来收发数据,就像打开一个句柄将数据写在存储器上一样,使用 socket 能将程序放在网络中,并与同一网络下其他计算机进行通信。
现在问题又来了,主机内部应用间进行通信,不同应用可用进程号作为唯一标识,那么在网络间通信用什么作为唯一标识呢?其实 TCP/IP 协议簇已经解决了问题,在网络层 IP 地址可以用作网络中主机的唯一标识,传输层的”协议+端口”可用作主机应用的唯一标识,因此利用三元组(IP地址、协议、端口)就可以标识网络应用了,网络应用间可以用三元组作为标志和其他应用进行交互,socket 通信大致如下:
在这里插入图片描述
如图所示,应用程序进程在网络间的通信全部通过 socket 与底层协议交互,进行网络通信,但是 socket 并没有层的概念,它只是一种设计模式(软件抽象层),方便编程而已。

编程流程

socket 编程的底层实现是基于 TCP 和 UDP 的,因此其编程的流程也是围绕着这两个协议的客户端、服务端来进行的,大致流程如下图:
在这里插入图片描述

socket函数

在实现上述功能的过程中,要用到很多接口函数,这一节就针对这些接口函数作详细解释。
1、socket()
这个函数作用是创建一个 socket 的操作对象,它被用作 socket 描述符的唯一标识(相当于文件描述符),在本地我们可以用这个对象进行文件操作,在主机远程连接时则可以用于建立连接、收发数据。
2、bind()
这是服务器端特有的接口函数,把 socket 对象和服务器的 IP 地址、开放端口绑定在一起,在 listen() 的调用下提供服务,客户端可以通过这个来连接服务器。但是客户端是没有 bind() 绑定地址和端口的,因为客户端不用发起监听,在客户端是在调用 connect() 时由系统随机生成一个。
3、listen()
也是服务器端特有的一个接口函数,作用是监听一个端口是否有数据发送过来,函数工作的时候会调用 bind() 函数,获取里面的套接字、地址和端口信息,如果有指向这个套接字描述符、本服务器地址和正在监听的这个端口的连接发送过来,则会让其通过并开始建立连接。
4、connect()
这个函数接口是 TCP 客户端特有的,用于向服务器发起连接建立请求。只要在 connect() 的参数中输入目标服务器的地址和端口,就会向目标发起连接请求,在服务端收到请求后就会调用 accept() 开始自动进行三次握手,从而建立连接。
5、accept()
这个函数接口是 TCP 服务端特有的,当 listen() 监听到请求后就会调用这个函数去建立连接,也就是说,只要这个函数执行成功,与客户端的连接就建立完成,并且可以互相传输数据了。
6、recv(),recvfrom()
这两个函数接口是用来接收数据的,recv() 方法对应 TCP 数据流,recvfrom() 则对应 UDP 数据流,因为 TCP 面向连接而 UDP 传输数据并不创建连接,所以要分这两种办法进行数据的接收。
7、send(),sendto()
和第 6 点的函数接口类似,但是用于发送数据的,和 recv()、recvfrom() 一起实现了网络中不同进程间的通信,其中 send() 对应 TCP 的传输方式,sendto() 对应的是 UDP 的传输方式。
8、read(),write()
这两个函数其实是通用的 I/O 读写操作,可以用来读写本地的文件,自然也可以用于网络间的读写操作。
9、close()
当客户端和服务端建立连接并处理完业务后,就要关闭相应的 socket 描述符以节省系统资源。在调用 close() 后,该 socket 描述字的引用计数 -1,不能够再由对应的调用进程使用,但是只有当引用计数=0 的时候,才会触发 TCP 客户端向服务端发起终止连接的请求。

协议

既然是通过底层协议进行信息传递,那么肯定少不了 OSI 七层模型:
科来公司网络通信协议图(部分)
现在有很多文章都讲得比较详细了,这里就只列出一些 socket 编程会用到的协议。

TCP

TCP 协议是一种面向连接的、可靠的、基于字节流的传输层通信协议,是为了互联网上提供可靠的端到端字节流而专门设计的,因此 TCP 协议做了一些规定:数据分片、到达确认、超时重发、滑动窗口、失序处理、重复处理、数据校验。
作为可靠传输的一种协议,它有以下特点:
1.基于流的方式
2.面向连接
3.网络不佳时尽量降低系统由于重传带来的带宽开销
4.连接维护面向通信的两个端点
在连接上,因为是可靠的,所以在建立连接的时候会进行三次握手,断开连接的时候则会进行四次挥手,在 socket 编程中体现如下:
在这里插入图片描述
在 socket 编程中,因为可靠性,TCP 是用的最多的连接协议,就连 http 协议也是基于 TCP 的。
当两台主机要建立 TCP 连接时,客户端要向服务端发送 SYN 包发起连接请求,服务端收到 SYN 包后获取到客户端地址然后响应一个 SYN+ACK 包进行确认,表示接受连接,客户端收到这个确认包后也会返回一个用于确认的 ACK,到这里连接就建立完成了,接下来就可以传输数据了;
如图所示,TCP 为了保证可靠性和降低开销,每次传输的数据是分片传输的,第一个分片会告诉服务端这一次有多少个分片要传输,传输序号为最后一个的分片则会告诉服务端数据传输完毕,服务端每接收一次数据包就会响应一个 ACK 确认,反过来也一样;
在断开连接的时候则要经过四次挥手,断开连接的发起方可以是客户端也可以是服务端,其中一方发送 FIN+ACK 包告诉另一端数据传输完毕,询问是否能够断开连接,另一端收到后响应一个 ACK ,如果数据未接收完成,则通过这个 ACK 告诉对方未接收完成,暂时不要断开连。若数据传输完毕,则会发送 FIN 给信息发送方,告诉对方数据接收完成,准备好关闭连接了,另一端接收到 FIN 包后响应一个 ACK,同时状态变成 TIME_WAIT,接收方收到 ACK 确认后就断开连接,发送端等待 2msl 后若没收到接收端新的信息也会断开连接。
上面的原理看起来很复杂,但是在 socket 层面就简化了很多,双方在连接前都要先建立好套接字,服务端还要开启监听,准备工作就完成了。客户端用 connect() 向服务端发起连接请求,服务端监听到请求后用 accept() 建立连接,这样三次握手就完成了;接下来连接双方都可以用 recv() 方法和 send() 方法进行数据的收发;数据传输完成后直接调用 close() 方法就可以完成四次挥手从而断开连接。

UDP

UDP 协议和 TCP 一样用来处理数据包,并且都位于传输层,不同的是 UDP 提供面向事务的简单不可靠信息传送服务,也就是说 UDP 协议的数据包发送后是没法知道是否安全、完整到达的,而且也不提供向 TCP 那样分片、重传、确认等功能,但是有个优点就是传输性能比 TCP 要高很多,毕竟不用分配资源去保证可靠性。因此在一些条件下 UDP 传输会更加实用。
在 socket 编程中,用 UDP 协议传输数据也非常简单,客户端和服务端双方分别绑定套接字,服务端开始监听,客户端用 sendto() 直接发送数据,然后调用 close() 关闭数据出口,服务端则用 recvfrom() 接收;一次 UDP 数据传输就结束了。虽然 UDP 传输非常节省资源,但是会存在各种问题,因此在编程的时候要注意:一个 UDP 包允许报文长度 <512 字节,而 TCP 报文允许 >512 字节。

DNS

DNS 协议即地址解析协议,作用是将域名和 IP 地址互相转换,因为是基于 TCP、UDP 协议工作的,因此可以通过 socket 编程来实现其中的一些功能。在这之前我们先简单了解一下 DNS:
首先,DNS(域名系统)是一个分布式数据库,被用来维护系统内每个主机名和 IP 的对应关系,用户输入域名时会自动查询 DNS 服务器,由服务器检索数据库,返回相应的 IP 地址;
如果指定的 DNS 服务器没有记录,则会向上一层次的 DNS 服务器发起查找请求,各逻辑的树形结构(域名空间结构)如下图:
在这里插入图片描述
在解析请求时,如果本地(hosts文件)没有目标信息,就会去询问其他 DNS 服务器,这个过程是逐级提交的,其由高到低的层次划分可以分为下面几大类:

分类 作用
根域名服务器 最高层次的域名服务器,全世界仅13台,负责管理顶级域名
顶级域名服务器 负责管理在该顶级域名服务器下注册的二级子域
权威域名服务器 负责一个区的域名解析工作
本地域名服务器 当主机发起DNS查询请求时第一个查询的对象,一般为主机hosts文件/本地DNS服务器

当其他 DNS 服务器返回查询结果时,该 DNS 服务器会把结果记录在本地缓存中,成为 DNS 缓存。
查询方式分为两种:
1.递归查询:在该模式下 DNS 服务器接收到客户机请求,必须使用一个准确的查询结果回复客户机。如果 DNS 服务器本地没有存储查询 DNS 信息,那么该服务器会询问其他服务器,并将返回的查询结果提交给客户机;
2.迭代查询:当客户机发送查询请求时,DNS 服务器并不直接回复查询结果,而是告诉客户机另一台 DNS 服务器地址,客户机再向这台 DNS 服务器提交请求,依次循环直到返回查询的结果为止。
基于这些理论,我们可以利用 socket 构造 DNS 查询请求,甚至可以把连接产生的 TCP 流量封装到 DNS 查询里,实现内网穿透。

HTTP

HTTP 协议(超文本传输协议)是现在互联网中最常用的一种网络协议,是一个标准的请求-应答模型(B/S),也就是说通信过程永远都是客户端发起请求,服务器返回响应信息,当然,也是基于 TCP 协议进行通信的。在客户机与服务器建立连接后,浏览器可以向 web 服务器发送请求并显示收到的网页,当用户在浏览器地址栏中输入一个 URL 时就会向 web 服务器发出 HTTP 请求,信息包括请求修饰符、客户端信息、提交的数据等,web 服务器接收到请求后对其进行处理并响应,响应的内容包括响应状态码、协议版本、服务器的部分信息、实体信息等,这些内容以 HTTP 规定的格式送回给客户端浏览器,浏览器对其进行显示。另外,HTTP 协议是无状态协议,即对事务处理没有记忆能力,在服务器不需要先前信息时应答速度就会很快。
在 socket 编程中也遵循这个模型,分为客户端、服务端,客户端可以构造请求,发送数据给服务器,服务端可以发布静态/动态资源,供客户端获取,或者提供 I/O 接口,进行数据交互,也可以通过连接数据库,实现数据存储、查询等功能。
其工作流程如下:
1.浏览器根据域名解析 IP 地址;
2.客户端通过浏览器与 web 服务器建立一个 TCP 连接;
3.客户端向服务端发起请求;
4.服务端响应客户端的 HTTP 请求,返回 html 代码;
5.客户端解析 html 代码,请求资源;
6.资源下载完毕后关闭 TCP 连接,浏览器对页面进行渲染然后呈现给用户。
客户端根据服务器的设置发起的请求有很多种,下面列出一些常见的请求方式:

方法 作用
GET 申请获取资源
POST 客户端向服务器提交数据的方法
HEAD 申请获取响应的头部信息
PUT 用于上传资源
DELETE 用于删除资源
TRACE 用于返回原始请求内容,可用来查看中间服务器对http请求的影响
OPTIONS 用于查看服务器对特定URL都支持哪些请求
CONNECT 用于代理服务器,可把请求的连接转换成隧道
PATCH 对资源做部分修改

每次请求的请求头都会附加一些信息,补充了请求的附加内容、客户端信息、相应内容相关优先级信息,下面是一些常见的请求头信息:

头部字段名 说明
Accept 用户代理可处理的媒体类型
Accept-Charset 优先的字符集
Accept-Encoding 优先的内容编码
Accept-Language 优先的语言
Authorization web认证信息
Expect 期待服务器的特定行为
From 用户邮箱地址
Host 请求资源所在的服务器
Proxy-Authorization 代理服务器要求客户端的认证信息
Range 实体的字节范围请求
Referer 对请求中uri的原始获取方式
TE 传输编码优先级
User-Agent 浏览器信息

而响应头则补充了资源内容更新时间等与实体有关的信息

头部字段名 说明
Accept-Ranges 是否接收字节范围的请求
Age 资源创建时间
ETag 资源匹配信息
Location 让客户端重定向到某uri
Proxy-Authenticate 代理服务器对客户端的认证信息
Retry-After 对再次请求的发起时机要求
Server 服务器的banner信息
Vary 代理缓存的管理信息
WW-Authenticate 服务器对客户端的认证信息

实体资源的头部:

头部字段名 说明
Allow 资源可支持的http方法
Content-Encoding 适用的编码方式
Content-Language 优先语言
Content-Length 网页资源的大小
Content-Location 替代对应资源的uri
Content-MD5 资源的md5值
Content-Range 资源的位置范围
Content-Type 接收的数据格式类型
Expires 资源过期的时间
Last-Modified 资源最后修改日期

除了上面的特征头部字段,还有通用的头部字段:

头部字段名 说明
Cache-Control 进行缓存操作的工作机制
Connection 控制不在转发给代理的首部字段,管理持久连接
Date 创建报文的时间
Pragma 编译报文指令
Transfer-Encoding 指定主体传输的编码方式
Upgrade 用于检测HTTP及其他协议是否可使用更高的版本进行通信
Via 代理相关信息
Warning 报错通知

HTTPS

HTTPS 是加密的 HTTP 通道,因为 HTTP 传输是明文的,存在信息泄露的风险,因此HTTPS就是在这基础上通过传输加密和身份认证保证了传输过程的安全性。
HTTPS 其实并不是应用层的新协议,而是在 http 接口通过 SSL、TLS 来加密和认证的机制,其加密过程如下:
1.客户端和服务器进行握手请求(https的握手)
2.协商加密算法
(客户端告诉服务器自己支持多少种加密组合,一个组合里面有 对称、非对称、hash、密钥交换算法,服务器选择自己支持的加密强度最高的一种)
3.服务器发公钥证书给客户端
4.客户端收到后在本地进行证书匹配(验证)
(本地有根证书能解开的就说明这个公钥是那个根证书的公司签名的,没有能解开的就是不受信任的)
5.客户端收到后在本地随机生成对称密钥(本次会话结束失效)
6.客户端把生成的对称密钥用服务器给的公钥加密发给服务器
7.服务器拿到用自己公钥加密的密文后用私钥解开,取得内容
开始传输数据(两边都有加密密钥)
8.客户端把加密的信息对应的hash值加了密的hash值发给服务器
(明文信息用对称密钥加密,然后做hash计算,生成固定长度的hash值,用得到的公钥证书里的公钥对这个hash进行加密,生成hash值(给hash加密))
9.服务器拿到这3部分信息后,用自己的私钥解开由自己公钥加了密的hash值,和客户端发的对应的hash值做比较,如果相同就表示没被篡改,再用客户端发的对称密钥解开加密的信息,再做hash计算,计算出的hash值和对应的hash值做比较,相同的话表示数据完整性没被破坏(身份验证)
10.服务器开始接收数据
在 socket 编程中也是可以实现 https,只是除了基本的 http 模块外还需要导入 SSL 相关的模块,编程的流程大致如下:
在这里插入图片描述
在这里插入图片描述
如果有不对的地方,还请各位大佬指出 ^ _ ^


相关文章:
多线程编程概念
Golang socket 编程
Python socket 编程
PHP socket 编程
Java socket 编程

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/180642.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 一、智能车舵机控制

    一、智能车舵机控制前言:本文章主要是近期有关舵机知识的总结,将分别从舵机的控制原理,控制流程和代码实现流程几个方面作简要介绍,由于时间紧急,难免有疏漏错误之处,欢迎留言指正,QQ:2046890259一、多级的控制原理:我们本次智能车使用的舵机是通过PWM进行控制。而PWM几个重要的参数就是最大值,最小值和占空比。其中占空比决定了舵机的旋转角度,如下图所示:不同的占空比控制不同的角度。而我们的目的就是通过…

  • 你想要了解的黑客入门知识在这里

    你想要了解的黑客入门知识在这里开篇特此声明,萌新博主所写这篇文章的初衷并不是想让大家成为一名黑客,去做出一些违反国家法律规定的违规操作,只是单纯的想介绍一下成为黑客所要了解的知识以及一些必要的黑客术语,从读者的角度去满足一些计算机爱好者的好奇心。博主心底善良,为人正直,遵守国家法律规定。如有违反,望各位读者监督,另外图谋不轨者,严禁转载!!————————————————分割线———————————————————————…

  • ubuntu16.04安装cuda10.2_opencv cuda

    ubuntu16.04安装cuda10.2_opencv cuda由于实验需要,在实验室电脑上搭建深度学习Caffee框架。一共花了两天的时间,其中遇到了不少的问题,记录一下。Caffee在配置上相对来说比较麻烦,需要前期安装的东西比较多,逐一介绍。CUDA:NVIDIA系列显卡支持的GPU编程框架,其实如果本身电脑是AMD的显卡,不用装也可用Caffee,只是速度会比较慢。所以最好有一块像样的显卡,最后我就败在这个上面了。。。MKA或是OpenAtlas

    2022年10月30日
  • stream.groupingBy多层分组_微信分组名称

    stream.groupingBy多层分组_微信分组名称Stream之Collectors.groupingBy(分组)的使用参考自:https://blog.csdn.net/u014231523/article/details/102535902Collectors.groupingBy配合Stream流使用,可以对集合中一个或多个属性进行分组,分组后还可以做聚合运算。首先把数据放入集合: Productprod1=newProduct(1L,1,newBigDecimal(“15.5″),”面包”,”零食”);Produ

  • 太原智慧小区有哪些_智慧城市规划

    太原智慧小区有哪些_智慧城市规划经过3个月的紧张施工,至7月初,位于龙城大街的“首开·国风上观”小区成为我市首个实现电、水、热采集“多表合一”的智能化小区。记者从国网太原供电公司了解到,该试点小区住户达3524户,是目前国内“多表合一”改造试点中规模较大的,也是我省试点中规模最大的小区。今年,国家发改委、国家能源局、工信部曾联合出台《关于推进“互联网+”智慧能源发展的指导意见》,其中…

  • Mac下 Vim删除多行快捷键

    Mac下 Vim删除多行快捷键Mac下,Vi和Vim是神一样的编辑器,如何删除多行。以下以编辑host文件为例首先在Terminal中,输入vim/etc/hosts,按return。进入vim的默认模式。Vim有三种模式命令模式,编辑模式,和默认模式按esc进入命令模式,可以使用退出,存盘退出,不存盘退出等命令。命令模式稍后整理按a进入编辑模式的ins

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号