在网络的通信的时候,都有听说过三次握手四次挥手。但是对其原理是否清晰?本篇文章通过使用wireshark对网络通信扑捉,进行原理分析。
1 BIO代码实现
- //服务端代码
- public class ServerSocket {
- public static void main(String[] args) throws Exception {
- //创建ServerSocket对象,用于客户端的连接
- java.net.ServerSocket serverSocket = new java.net.ServerSocket(8989);
- //定义输入流对象读取数据
- byte[] bytes = new byte[1024];
- try {
- while (true) {
- System.out.println("服务端发生阻塞,等待连接....");
- //调用accept方法监听客户端,阻塞方法
- Socket accept = serverSocket.accept();
- //调用Socket对象的方法获取输入流对象
- InputStream inputStream = ((Socket) accept).getInputStream();
- System.out.println("服务端发生阻塞,等待接收数据....");
- int read = inputStream.read(bytes);
- System.out.println(new String(bytes, 0, read));
- //关闭资源
- accept.close();
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- if (serverSocket != null && !serverSocket.isClosed()) {
- serverSocket.close();
- }
- }
- }
- }
- //客户端代码
- public class ClientSocket {
- public static void main(String[] args) throws Exception {
- //创建Socket对象,与服务端Socket建立连接
- Socket socket=new Socket("127.0.0.1",8989);
- //获取输出流对象
- OutputStream outputStream=socket.getOutputStream();
- System.out.println("客户端阻塞,接收键盘输入....");
- //接收键盘输入,模拟延迟消息发送
- Scanner scanner=new Scanner(System.in);
- String scannerString=scanner.next();
- outputStream.write(scannerString.getBytes());
- System.out.println("客户端录入完成....");
- //使用输出流对象写入数据
- // outputStream.write("itheima-TCP".getBytes());
- //释放资源
- socket.close();
- }
2 Socket的API(构造方法)
- Socket():无参构造方法。
- Socket(InetAddress address,int port):创建一个流套接字并将其连接到指定 IP 地址的指定端口。
- Socket(InetAddress address,int port,InetAddress localAddr,int localPort):创建一个套接字并将其连接到指定远程地址上的指定远程端口。
- Socket(String host,int port):创建一个流套接字并将其连接到指定主机上的指定端口。
- Socket(String host,int port,InetAddress localAddr,int localPort):创建一个套接字并将其连接到指定远程地址上的指定远程端口。Socket 会通过调用 bind() 函数来绑定提供的本地地址及端口。
3 Socket的API( 普通方法)
- void bind(SocketAddress bindpoint):将套接字绑定到本地地址。
- void close():关闭此套接字。
- void connect(SocketAddress endpoint):将此套接字连接到服务器。
- InetAddress getInetAddress():返回套接字的连接地址。
- InetAddress getLocalAddress():获取套接字绑定的本地地址。
- InputStream getInputStream():返回此套接字的输入流。
- OutputStream getOutputStream():返回此套接字的输出流。
- SocketAddress getLocalSocketAddress():返回此套接字绑定的端点地址,如果尚未绑定则返回null。
- SocketAddress getRemoteSocketAddress():返回此套接字的连接的端点地址,如果尚未连接则返回 null。
- int getLoacalPort():返回此套接字绑定的本地端口。
- intgetPort():返回此套接字连接的远程端口
4 WebSocket的API(构造方法)
- ServerSocket():无参构造方法。
- ServerSocket(int port):创建绑定到特定端口的服务器套接字。
- ServerSocket(int port,int backlog):使用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口。
- ServerSocket(int port,int backlog,InetAddress bindAddr):使用指定的端口、监听 backlog 和要绑定到本地的 IP 地址创建服务器
5 WebSocket的API(普通方法)
- Server accept():监听并接收到此套接字的连接。
- void bind(SocketAddress endpoint):将 ServerSocket 绑定到指定地址(IP 地址和端口号)。
- void close():关闭此套接字。
- InetAddress getInetAddress():返回此服务器套接字的本地地址。
- int getLocalPort():返回此套接字监听的端口。
- SocketAddress getLocalSoclcetAddress():返回此套接字绑定的端口的地址,如果尚未绑定则返回 null。
- int getReceiveBufferSize():获取此 ServerSocket 的 SO_RCVBUF 选项的值,该值是从ServerSocket 接收的套接字的建议缓冲区大小。
- accept()方法会返回一个和客户端Socket对象相连的Socket对象。使用Socket的getOutputStream可以向客户端发送信息。使getIutputStreamke可以获取客户端传过来数据。
6 TCP协议中,建立连接三次握手
1.简述
在tcp协议中,双方建立连接的时候是需要三次握手。这个连接建立需要一方主动打开,另外一方被动打开的。下图为建立连接图解。
上图解释
SYN(建立连接) 请求建立连接,并在其序列号字段进行序列号的初始值设定。建立连接,设置为1。
ACK(acknowledgement 确认) 确认号是否有效,一般置为1
PSH(push传送) 提示接受端应用程序立即从TCP缓冲区把数据读走。
FIN(finish结束) 希望断开连接。
RST(reset重置) 对方要求重新建立连接,复位。
URG(urgent紧急) 紧急指针是否有效。为2,表示某一位被优先处理。
2. 网络请求建立连接,经历三次握手流程
a 第一次握手
在第一次"握手"时,客户端向服务端发送SYN标志位,目的是与服务端建立连接。Seq代表sequence,number(发送数据流序号), 例如:Seq的值是5,说明在数据流中曾经一共发送了 1, 2, 3,4 这4次数据。而在本次"握手"中, Seq的值是0,代表客户端曾经没有给服务端发送数据。另外Len=0也可以看出来是没有数据可供发送的,客户端仅仅发送一个SYN标志位到服端代表要进行连接。
b 第二次握手
第二次"握手"时,服务端向客户端发送 SYN ACK 标志位,其中ACK标志位表示是对收到的数据包的确认,说明服务端接收到了客户端的连接。ACK的值是1,表示服务端期待下一次从客户端发送数据流的序列号是1,而Seq=0代表服务端曾经并没有给客户端发送数据,而本次也没有发送数据,因为Len=0也证明了这一点。
c 第三次握手
第三次“握手”时,客户端向服务端发送的ACK标志位为1, Seq的值是1。Seq=l代表这正是服务端所期望的Ack=1。Len=0说明客户端这次还是没有向服务端传递数据,而客户端向服务端发送ACK 标志位为1的信息,说明客户端期待服务端下一次传送的Seq的值是1。
3. 为什么要进行三次握手
为了防止服务器端开启一些无用的连接,增加服务器开销。以及防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。
7 TCP协议中,连接断开时候(四次挥手)
1. 四次挥手
即TCP连接的释放(解除)。连接的释放必须是一方主动释放,另一方被动释放。以下为客户端主动发起释放连接的图解:
简述流程
2. 四次挥手执行流程
注意 BIO存在问题
1 客户端已经连接服务端,尚未发送数据,read阻塞
2 新的客户端无法正常连接
解决办法
1 线程解决(mysql客户端连接服务器)
2 线程池解决(线程池泄露)
3 NIO解决
4 websocket
人脸识别访客系统的好处有哪些 以往人们采用手写登记进行来访者管理,虽然登记簿...
3 月 8 日消息 在今日举行的第十三届全国人民代表大会第四次会议后,各位负责人...
昨天微信出现了bug, 很多人无法接收到信息 ,微信刚道完歉,今天企业微信也崩溃...
【51CTO.com快译】无处不在的传感器每天都在收集大量图像,而使用人工智能技术自...
据外媒报道,巴西通信部长法比奥法里亚(Fabio Faria)在国会5G工作组公开听证会上...
一夜之间,苹果App Store成了人类公敌,Facebook、Spotify、Epic都向苹果发难。...
能源行业属于高技术驱动性行业。由于需要在严苛的条件下处理大型设备中的各类自...
总结一下各大产品在「隐私保护」这方面的做法与设计点,今后面对用户隐私信息设...
携号转网,曾被认为是推动国内电信业务充分竞争的重要举措,无数用户期待此举能...
苹果于昨日向所有 iPhone 用户推送了最新的 iOS 13.7 更新,带来了一些重大的改...