Socket-TCP快速入门:

TCP是什么?

英语:Transmission Control Protocal,缩写为TCP [træns'mɪʃən]n. 传动装置,[机] 变速器;传递;传送;播送

TCP是传输控制协议;是一种面向连接的 可靠的 基于字节流的传输层通信协议,有IETF的RFC 793定义。

与UDP一样完成第四层传输层所指定的功能与职责。

TCP的机制:

三次握手,四次挥手。

具有校验机制、可靠、数据传输稳定。校验机制保证了数据传输的可靠性以及数据传输的稳定性,那么数据传输的可靠性呢,在于我们的客户端往服务器端发送数据的时候,数据会经过层层的校验,以便后面的数据是否确定可以进行发送,当然服务器端给客户端回送消息的时候也会经过这样的一个校验机制,所以说可以保证咋们的数据可靠性。

那么数据传输的稳定性呢,这在于我们数据传输的一个速率的窗口大小的随机调整。原理大概是:客户端给服务器端发送数据的时候,由于受限于我们客户端或者服务器端的带宽压力,或者是客户端和服务器端处理能力的压力,那么当客户端有100个字节发送到服务器端的时候,如果发现服务器端的数据接收过于缓慢,那么服务器端会在接收过程当中定期的回送他自己的一个状态给客户端,那么客户端也会根据这样的状态进行自己的一个速度调整,以便自己客户端的速度适应服务器端的一个接收速度,从而满足咋们的一个数据传输稳定性。

TCP连接、传输流程:

首先客户端的连接经过了3次握手连接到服务器端,然后服务器端在经过这3次握手连接成功之后,才会进入到我们后续的一个传输的建立,后面的传输建立后就好发送一系列的数据过去同时又回送数据,这是客户端和服务器端简单交互的流程介绍。TCP当中会有一些额外的数据进行发送,例如校验数据,如果你发送的数据为100K,那么可能发送完成之后,你的数据字节会大于100K,这是正常的,因为在整个过程当中TCP和服务器端会不断的进行一个数据的校验,以及咋们的一个连接建立,这些都是需要消耗额外的一些流量,这样咋们额外的一些数据的消耗。

TCP能做什么?

聊天消息传输、推送。

单人语言、视频聊天等。这个点如果用UDP来做的话会更加优秀一点,他在传输上的一些限制会更小,当然如果你想要保证单人之间传输的一个优越性、数据的一个健壮性、以及保证视频数据的一个精准送达,那么可以用TCP来做。

几乎UDP能做的都能做,但需要考虑复杂性、性能问题。

限制:无法进行广播,多播等操作。这是UDP所独有的。也无法做搜索,搜索只能由UDP来做。

TCP核心 API讲解:

socket(): 创建一个Socket。在于创建一个客户端的Socket连接,客户端自己new Socket的时候,其实他通过构造函数创建一个无连接的无绑定的一个客户端Socket的空状态。一般而言是创建一个空状态的Socket,后面在调用方法设置参数建立连接。
bind(): 绑定一个Socket到一个本地地址和端口上。对于客户端而言就在于绑定到你自己客户端的端口上。而对于服务器端而言bind这个方法呢在于绑定在自己服务器端的一个接口上之后,那么他还监听这个地址和端口上所到来的其他的客户端的一些套接字。
connect(): 客户端连接到远程套接字。
accept(): 接受一个新的连接。这是服务器端的一个ServerSocket所独有的一个方法。这是一个阻塞方法,等待客户端连接。可是设置超时时间。阻塞状态直到有一个新的客户端连接到达,才会进入到后面的Socket创建。那么服务器端的一个简单流程就是一个ServerSocket绑定到一个自己的端口之后,会进入到一个accept的等待状态,如果此时有新的客户端的Socket到达,那么这个时候服务器会创建一个对应的相匹配的Socket,进入到后续的一个发送和接受的流程。那么服务器端还可以自己选择是否再去accept下一个Socket或者是直接关闭掉,不再进行后续的一个套接字的等待。
write(): 把数据写入到Socket输出流。
read(): 从Socket输入流读取数据。
复制代码

客户端流程:

创建Socket-->bind本地套接字(占用一个本地端口)-->connect远程套接字-->如果连接成功,客户端就可以和远程套接字服务器进行数据收发。

服务端流程:

创建ServerSocket-->bind本地套接字-->accept客户端套接字-->如果此时客户端的连接到达了,那么远程套接字服务器就可以和客户端之间 进行数据的收发。

扩展-Socket与进程关系:

默认的每一个进程都可以创建一个Socket连接,甚至你的一个进程可以创建多个Socket连接。可以借助于Socket来进行进程之间的数据交互。

TCP的buffer以及TCP底层的变量其实是由操作系统所维护的,那么TCP在进行这些变量以及buffer的一些维护得到信息之后,他会信息抛给上层的进程这一层,所以咋们进程这一层其实是无法管理咋们TCP底层的一些东西的,比如咋们前面说的TCP三次握手,四次挥手,以及TCP的数据校验机制这些东西,是由TCP系统所完成的,系统其实是实现了TCP的协议的,这些东西无序我们进程去关心,我们进程仅仅只是使用TCP,从而实现了进程之间的一个交互。当然进程之间的交互并不仅仅只是你自己电脑上的进程交互,其实是你电脑的某个进程和别人电脑上的某个进程之间的一个交互,这也是属于进程之间的一个交互。

TCP连接可靠性:

  • 三次握手: 首先客户端TCP会发送一条叫做SYN命令(这是一个连接请求命令),这个命令会携带一个参数,暂且叫x=rand()随机值,随机值在发送给服务器之后,服务器这个时候还没有进行一个连接的建立,仅仅只是受到了这样一次命令,收到这个命令之后他会做一个操作,校验收到的这个SYN命令,如果这个命令是完整的,那么他会开始回送一条命令,回送的命令叫SYNACK,这么命令当中携带了两个指令,一个是SYN指令,一个是ACK指令,ACK指令是对客户端发送过来的SYN指令的一次回送,这个回送代表着服务器端自己已经收到了客户端的一个信息,同理他在回送这个命令的时候也会携带一条命令SYN命令过去到客户端,在这个过程当中首先他会做一件事情,在回送咋们的ACK命令的时候他会携带我们客户端所带过来的这个x,客户端在发送SYN命令的时候会把x发送到服务器端,那么服务器端在回送这条ACK命令的时候,其实他会回送这个x回去,那x这个时候会做一个操作,把这个x+1代表着他已经收到并且经过了一次处理,所以他把x+1,然后回送到客户端,当然同时在回送的时候,他会自己携带一条他自己的SYN命令,这条命令会携带第二个参数y=rand()随机值,生成方式和客户端发送过来的x生成方式一模一样,这个时候回去的有两个命令,一起到达客户端,在客户端收到的时候,他会先进行一次校验,如果说认为自己发送的SYN这个命令,收到的这个ACK命令呢是等于x+1的,那么就认为这一次已经收到服务器的一个回送消息,同时他会给服务器回送一次说我已经收到了,那么他给服务器回送消息的时候,他会把y+1同时包括刚刚收到的x值发送给服务器端,服务器端在收到这个ACK命令之后,确保这个连接已经完全的建立,之后就可以进行咋们数据发送上的一些准备和操作。那么在这里要说一下为什么要有这样的一个3次命令?首先客户端跟服务器说我要连接你,服务器端给客户端说你可以来连接我,当然服务器也给客户端同时说我也要连接你,那么这个时候客户端给服务器回送说,你可以连接我。这个地方可以确定两个事情,客户端可以连接服务器,那么服务器也可以连接客户端。其中的随机数是用于确定对应的客户端的,因为服务器端是要接受无数的客户端连接。

  • 四次挥手: 客户端也可以是服务器端,这里在于这里是发送方,对面是接受方,其实无论是客户端还是服务器端都可以进行这样的一个流程,都可以提出自己想要关闭的一个操作。首先他们会从一个已连接的状态先发送一个FIN命令FIN=1(1也是随机值),seq=u(随机值)。当接受方收到这条消息的时候,他会回送你一条ACK命令,ACK命令都是一个回送命令,ACK=1,seq=v,ack=u+1,当发送方一旦收到这个ack=u+1的时候,那么你其实就已经可以把你自己的连接断开了。这个时候服务器端有可能还有一些数据没有给你完全送达,这个时间之内,服务器端会把他没有完全送达的消息一一给你送达,知道他送达 完成之后,他才给你发送一个FIN=1,ACK=1,seq=w,ack=u+1命令过来说他想要关闭了,就是服务器端跟你说他想要关闭这个连接,他一旦给你发送了这个消息之后,你收到这个消息之后,你会给他回一个ACK=1,seq=u+1,ack=w+1命令,一旦这个ACK命令你确保他已经收到了,那么之后就可以进行一个连接断开了,但这里其实就只有一个来回来回,你怎么确定一个数据被他收到了呢,其实是这样的,当咋们的服务器端他发送FIN命令之后,他会进行一个等待状态,在这个等待状态当中,他会持续的发送FIN命令,间隔一段时间之后会发送一次FIN命令,这个间隔时间呢一般是一次数据片所送达的完整的一个送达时间 这个简称叫SML,在于说一次数据片所能够达到对面的一次最长时间,那默认这个时间定义为2分钟,当然在Linux系统当中已经把这个值改为了30秒,30秒认为已经是一个现在网络非常可靠的一个时间,如果说30秒之内对方没有收到你的消息,那么就可以认为这条消息可能被网络断开丢掉了,现在的网络当中基本上可以保证在30秒之内把一个数据片送到对方。他发送一个FIN命令之后他会进行一个等待状态,在等待状态当中如果超过30秒,他会没有收到ACK命令,那还会继续发FIN命令给你,持续的发送,直到说你给他回送一次ACK命令,当然在这个过程当中有可能遇到说我网络出问题异常断开了,那么也是有可能会出现IO异常,这也是允许的,在这个过程当中,他给你发送,你给他回送的ACk命令之后,也是一样的,如果说这个连接还没有进行一个完整的断开,那么你会不断的收到FIN命令,因为对方在没有收到ACK命令的情况下,他间隔一段时间又会给你发送一个FIN命令,如果说你持续的收到FIN命令,你就要持续的向对方发送ACK表示你已经收到这个命令了,直到对方已经真实的收到了ACK命令之后,对方就把连接断开,你也把连接断开。四次挥手为什么要有四次挥手,四次挥手其实是保证了前面我们所说的全双工连接的一个断开,什么是全双工?就是说你可以向对面发送一条消息也可以接受来之对面的消息,对面可以接受你的消息,也可以向你发送消息。全双工在于你们之间断开连接,首先你向对面说可以关闭连接吗,对面一旦向你回复了可以允许断开连接,那么这个时候你就已经断开了你的一个输出流,你的输出流如果还在进行一个输出的话,那么会直接触发一个连接异常。当然这个时候你的输入还是保留的,因为你还可以接受一个来之服务器端的数据,服务器端这个时候还在向你发送数据,那么这个时候你自己其实是处于一个半双工的状态,你仅仅只能够接受消息了,不能再发送消息。那么服务器端也是一样,他把自己的消息发送完成之后,他向你回送了一条消息说,他的消息发送完了他也想要关闭连接,那么这个时候一旦你回送了一条消息确认,那么它也会把自己的一条连接断开,之前你们已经断开了一次你的发送信息的一个流,之后他断开了他向你发送信息的流,那么你不向说话了,他也不向你说话了,你们两者之间就可以确定已经断开了,所以这就是四次挥手所具备的一个功能。

TCP传输可靠性:

  • 排序、顺序发送、顺序组装。当你进行一条数据发送的时候,首先TCP会将这个数据拆分成不同的片段,然后把片段进行一个排序,之后把刚刚 排序的片段 顺序的组装之后进行发送,这就保证了数据传输的有序性。
  • 丢弃、超时。一旦在真个发送过程当中,你的一个数据片没有到达或者是数据片到达的时候超时,那么在TCP的客户端和服务器端当中,在客户端 其实是能够收到一个数据被丢弃或者说数据超时的一个消息的。那么一旦收到这样的消息,那么客户端要做的事情是他自己把这条信息重新 的进行一次发送,这就是TCP的一个发送流程,他首先把大的数据拆分成不同的数据片,然后把数据片排序,排序好之后一片一片的进行发送 当然这个一片一片的数据发送,为什么要做这个操作?首先为什么要拆分一个大的数据包,比如说客户端要发送一个大的数据包到服务器端, 一旦数据出现了一个传输上的问题,那么你这一整个数据包都被浪费丢弃掉了,而我们前面传输了20%的数据,其实都是无效的。你要重新 传输要从0开始传输,那么无疑是浪费比较多的流量的,那么为了尽可能的减少这样的一个流量消耗,所以他要把一个大的数据包拆分成很多 很多的小的数据包,当然拆分之后再进行发送其实也是增大了他的流量消耗,但是从整个体系上来讲,他是减少了一个浏览传输的一个消耗。 这是为了保证他的传输可靠性的一个流量消耗,这是允许的。 排序之后发送这个数据,发送数据有可能出现丢失,那么丢失的,我们认为仅仅是需要把刚刚丢失的部分数据进行重新发送即可,所以就需要 你一个顺序发送以及一个顺序组装,所以也就涉及到了咋们的一个数据丢弃和数据超时,那么这个一整套流程是TCP底层为我们完成的。
  • 重发机制-定时器。如果说在服务器端收到这个信息的时候,他会进行一个定时器会定时的给我们回送一些已经收到的数据片,那么客户端也是一样 当我们在一定的定时器范围之内没有收到服务器回送的消息的话,那么我们就认为没有被服务器端送达,我们会重新把这个数据在发送一遍, 一遍我们的数据一定是运行被发送到服务器端的,这样就保证了传输的可靠性。

TCP数据传输的一个流程:

左边是接收方,右边是发送方,发送方缓冲区有1 2 3 4 5,5个数据片。

首先他会给接受方发送第1个数据包{序列号=1,数据:1460byte},当接受方接受到的时候,他会回送一条{序列号=1,确认号=1461,数据:0byte},这时候缓冲区的指针会移动到2。

发送第2个数据包{序列号=1461,数据:1460byte}给接受方,发送过去之后,这个时候如果说发送方没有收到接收方的回送,那么这个回送被中断了,这个时候,发送方缓冲区的指针移动到了3位置,然后他把第3个数据包{序列号=2921,数据:1460byte}发送给接收方,这个时候发送失败,接受 方没有收到第3个数据包,发送方这时候缓冲区的指针会移动到4。

给接受方发送第4个数据包{序列号=4381,数据:1460byte},发送过去之后,这个时候如果说发送方没有收到接收方的回送,那么这个回送被中断了,这时候缓冲区的指针会移动到5。

首先他会给接受方发送第5个数据包{序列号=5841,数据:1460byte},当接受方接受到的时候,他会回送一条{序列号=1,确认号=2921,数据:0byte}然后接收方1 2 4 5都接受到了,但这个时候有一点是丢掉了一条数据,那么你丢掉的这条数据,如果说在发送方认为时间Timeout了,还没有收到你的回送,就认为这条数据真的是被丢掉了,那么他会把第三条数据重新发送。

发送方给接受方重发第3个数据包{序列号=2921,数据:1460byte},当接受方接受到的时候,他会回送一条{序列号=1,确认号=7301,数据:0byte}。

一条Socket连接视为一个通道。

TCP基础类型数据传输:

byte(8bit)、char(8big)、short(16bit)

char和byte是可以直接复用的,short要转换成2个byte数组。

boolean(8bit)、int(32bit)、long(64bit)

float(32bit)、double(64bit)、string(可变的) 中文转换成byte是3个byte。

UDP辅助TCP实现点对点传输案例: 如果说你知道你的服务器地址以及端口,那么往往你可以直接用TCP跟你的服务器进行一个连接。但是假如说在一个局域网当中,不知道你服务器 的一个IP地址,你仅仅知道的是你服务器公共的UDP的端口,那么在这样的情况下,你如何实现TCP的一个连接呢? TCP连接必须要知道IP地址和端口,那么要怎么要知道IP地址和端口呢?我们可以通过UDP的一个搜索,当我们的服务器与我们的所有的客户端之间 约定了搜索的一个格式之后,我们可以在客户端发起一个UDP广播,在广播的一个接受者,也就是服务器收到这个广播之后,然后判断一下我们的 这个收到的广播是否是需要处理的,如果说是,那么服务器会回送这个广播对应的端口和IP地址上面去,当这个回送的时候,客户端就能收到咋们 服务器回送过来的这个UDP的包,当收到UDP包的时候,UDP的包就包含了IP地址和端口号,当然还可以在服务器回送信息的时候携带一些信息,所以 我就可以通过UDP的一个搜索得到我们TCP需要的点对点的IP地址和端口,然后再根据这些信息建立TCP连接。

UDP搜索IP和端口:

构建基础的口令消息。如果说我们没有这个口令的一个头字节的话,那别人发的任何消息只要到达咋们的端口,咋们就会去回送,这是会暴露咋们自己的信息,比如最基本的信息IP地址和端口号。 局域网广播口令消息(指定端口)。

接受指定端口回送消息(得到客户端IP、port)。UDP没有标准的客户端和服务端,这里客户端指的就是对面的这一端就是server端。

UDP搜索取消实现:

异步线程接受回送消息。

异步线程等待完成(定时)。

关闭等待-终止线程等待。 一旦超时等待到达,我们就要进行一个线程的关闭,并且终止线程等待。

Socket IO与NIO(三)相关推荐

  1. Socket IO与NIO(二)

    UDP: 英文:User Datagram Protocal,缩写为UDP. 是一种用户数据报协议,又叫用户数据报文协议. 是一个简单的面向数据报的传输层协议,正式规范为RFC 768. 用户数据协议 ...

  2. node.js 之 socket.io

    2019独角兽企业重金招聘Python工程师标准>>> 1 Install Node.js on Ubuntu sudo apt-get install python-softwar ...

  3. Vue全家桶+Socket.io+Koa2打造一个智能聊天室 接口已开放

    Vue.js+Socket.io+Koa2打造一个智能聊天室 Vue.js全家桶+Socket.io+Express/Koa2 打造的一个智能聊天室. 已经开源啦!为了方便大家学习,智能机器人.IP定 ...

  4. io读取一个文件再写入socket技术_JAVA中IO与NIO面试题

    BIO.NIO有什么区别? BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低. NIO:New IO 同步非阻塞 IO,是传统 IO ...

  5. SOCKET编程 IO与NIO

    socket是网络编程的基础,通过socket不同的计算机之间可以进行数据的交互. JAVA中IO操作是阻塞的,每个操作都要创建一个线程,容易对资源造成浪费.而NIO的出现解决了这一点,NIO可以通过 ...

  6. 使用React、Node.js、MongoDB、Socket.IO开发一个角色投票应用的学习过程(三)

    前篇 使用React.Node.js.MongoDB.Socket.IO开发一个角色投票应用的学习过程(一) 使用React.Node.js.MongoDB.Socket.IO开发一个角色投票应用的学 ...

  7. Java之IO,BIO,NIO,AIO

    2019独角兽企业重金招聘Python工程师标准>>> 参考文献一 IO基础知识回顾 java的核心库java.io提供了全面的IO接口.包括:文件读写.标准设备输出等.Java中I ...

  8. 五.Java IO、NIO、文件、通讯

    2019独角兽企业重金招聘Python工程师标准>>> Java 的 I/O 大概可以分成四组: 基于字节操作的 I/O :InputStream 和 OutputStream 基于 ...

  9. Java NIO:IO与NIO的区别

    一.概念 NIO即New IO,这个库是在JDK1.4中才引入的.NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多.在Java API中提供了两套N ...

最新文章

  1. 智能家居市场年增速近30%!苹果看齐亚马逊、谷歌,欲开辟三足鼎立
  2. mysql localhost和127.0.0.1的区别
  3. Github新建分支以处理原仓库提交时detached HEAD的问题
  4. 深入理解分布式技术 - ZooKeeper数据一致性解读
  5. mysql 临时表 概念_临时表的概念
  6. win10+tomcat+php+配置环境变量配置,Win10系统Tomcat环境变量配置方法
  7. postgresql 备份 java_用JAVA执行CMD命令备份PG数据库,解决需要输入口令的问题
  8. 解决WORD文档无法显示链接的图像问题
  9. 关于uni-app框架下,用户真实头像采集的优化方案
  10. 《Redis视频教程》(p6)
  11. cad缩放_CAD中的AL是什么指令? 怎么操作哦
  12. mifs算法 matlab,信息安全工程师教程协议分析深度流检测技术(DFI)真题习题与考点...
  13. 触动人心的手机端页面设计
  14. windows cmd字典
  15. 2019年,大前端技术趋势程度解读
  16. 计算机主机房的消防配置,计算机机房消防安全审核标准
  17. 【Linux共享内存】
  18. Android开发必备(干货源码放送大)
  19. 集训队每周一赛2020-03-06(思维+暴力)
  20. 21岁被人“封神”,曾一分钟黑了阿里巴巴后台系统!

热门文章

  1. 64bit centos如何编译 32bit的程序
  2. linux nm 和ar命令
  3. 874. 模拟行走机器人
  4. mysql:ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
  5. Ubuntu 14.04 16.04 安装最新的 docker
  6. CentOS7 正确安装mysql(亲测)
  7. 获取repeater控件模版列中的控件
  8. 华为的数字化转型与数据治理
  9. 手把手教你用Python搭建一个AI智能问答系统
  10. 你是怎样“被平均”的?细数统计数据中的那些坑