套接字(Socket)全面解析:从概念到应用,配合TCP三次握手、四次挥手及Java代码、netstat讲解

套接字(Socket)全面解析:从概念到应用,配合TCP三次握手、四次挥手及Java代码讲解

今天我们来聊一聊Socket网络套接字。在网络通信中,套接字可以被视为通信的端点,每个套接字都有一个唯一的地址,包括IP地址和端口号。套接字之间的连接是基于这个地址的。

在Java中,我们可以使用java.net.Socket类来创建客户端套接字,使用java.net.ServerSocket类来创建服务器端套接字。

套接字代码示例

以下是建立客户端和服务器端连接的基本步骤:

  1. 服务器端:创建一个ServerSocket实例并绑定到一个特定的端口。然后调用accept()方法来监听来自客户端的连接请求。这个方法会阻塞,直到一个客户端连接到服务器。一旦有客户端连接,accept()方法就会返回一个新的Socket对象,这个对象代表了和客户端的连接。
  2. 客户端:创建一个Socket实例并指定服务器的IP地址和端口号。然后调用connect()方法来连接到服务器。

以下是一个简单的Java代码示例:

服务器端

import java.net.*;

public class Server {
    public static void main(String[] args) throws Exception {
        // 创建一个ServerSocket实例并绑定到端口8000
        ServerSocket serverSocket = new ServerSocket(8000);
        
        System.out.println("服务器已启动,等待客户端连接...");
        
        // 监听来自客户端的连接请求
        Socket clientSocket = serverSocket.accept();
        
        System.out.println("客户端已连接:" + clientSocket.getInetAddress());
        
        // 这里可以进行数据和客户端进行交互...
    }
}

客户端

import java.net.*;

public class Client {
    public static void main(String[] args) throws Exception {
        // 创建一个Socket实例并连接到服务器(假设服务器的IP地址是localhost,端口是8000)
        Socket socket = new Socket("localhost", 8000);
        
        System.out.println("已连接到服务器:" + socket.getInetAddress());
        
        // 这里可以进行数据和服务器进行交互...
    }
}

在这个例子中,服务器端首先启动并等待客户端的连接。一旦客户端连接,服务器端就会打印出客户端的地址。在客户端代码中,它首先连接到服务器,然后打印出服务器的地址。

套接字状态

服务器端(Server)

创建一个ServerSocket实例并绑定到端口8000。此时,服务器端的套接字(ServerSocket)处于监听状态,等待客户端的连接请求。
使用accept()方法接受来自客户端的连接请求。这个方法会阻塞,直到一个客户端连接到服务器。一旦有客户端连接,accept()方法就会返回一个新的Socket对象,这个对象代表了和客户端的连接。此时,服务器端的套接字(Socket)处于连接状态

客户端(Client)

创建一个Socket实例并连接到服务器(假设服务器的IP地址是localhost,端口是8000)。此时,客户端的套接字(Socket)处于连接状态

所以,根据代码的分析,我们可以说:

服务器端的套接字在创建后首先处于监听状态(等待客户端的连接请求),然后在接收到客户端的连接请求后,变为连接状态。
客户端的套接字在创建后直接处于连接状态

其中服务端 serverSocket.accept()方法用于在服务器端接受客户端的连接请求。当客户端发起连接请求时,服务器通过accept()方法接受请求,并返回一个新的Socket对象,我们称之为clientSocket。这个新的Socket对象代表了服务器和客户端之间的连接。

Socket对象信息

clientSocket对象中包含了以下信息:

  1. 连接状态clientSocket对象的连接状态表示客户端和服务器之间的连接是否已建立。可以使用isConnected()方法来检查连接状态。
  2. 输入/输出流clientSocket对象提供了输入和输出流,用于在客户端和服务器之间传输数据。可以使用getInputStream()getOutputStream()方法获取输入和输出流对象。
  3. 地址信息clientSocket对象包含了客户端的地址信息,包括IP地址和端口号。可以使用getInetAddress()方法获取客户端的IP地址,使用getPort()方法获取客户端的端口号。
  4. 关闭连接clientSocket对象提供了close()方法,用于关闭客户端和服务器之间的连接。
  5. 发送/接收数据clientSocket对象提供了send()receive()方法,用于向客户端发送数据和从客户端接收数据。这些方法可以在服务器和客户端之间传输数据。

需要注意的是,clientSocket对象是在服务器端创建的,它代表了服务器端和客户端之间的连接。服务器端可以通过clientSocket对象与客户端进行通信,发送和接收数据。一旦连接关闭,clientSocket对象将不再可用,需要重新接受新的连接请求。

结合TCP三次握手讲解套接字

当客户端向服务器发起连接请求时,会创建一个新的Socket并发送SYN报文给服务器。服务器在接收到SYN报文后,会为这个连接创建一个新的Socket,并向客户端发送SYN-ACK报文。在完成三次握手后,客户端和服务器都会为这个连接维护一个Socket。

如果一个服务器同时处理多个连接,那么它就会有多个Socket。同样,如果一个客户端同时与多个服务器进行连接,那么它也就会有多个Socket。

netstat查看套接字状态

现在,我将解释如何使用netstat命令来查看这些套接字的状态。在Linux或Unix系统中,可以使用netstat命令来查看套接字的状态。netstat命令用于显示网络统计信息,包括打开的套接字、路由表、接口统计等。

例如,要查看所有活动的套接字和它们的状态,可以运行以下命令:

netstat -alpt

在这里插入图片描述

如上图所示,显示所有套接字的列表,包括它们的本地地址、远程地址、状态等。在"State"或"Status"列中,你可能会看到如下几种状态:

LISTEN:服务器端的套接字正在监听来自客户端的连接请求。
ESTABLISHED:连接已经建立,数据可以在两个方向上传输。
SYN_SENT 或 SYN_RECV:连接正在建立过程中。这是TCP三次握手过程的一部分。
TIME_WAIT 或 CLOSE_WAIT:连接已经关闭,但还在等待一些资源释放。
FIN_WAIT1 或 FIN_WAIT2:一端的连接已经关闭,等待另一端的响应。
LAST_ACK:等待所有剩余的数据包被确认后关闭连接。
CLOSED:连接已经完全关闭。

TCP三次握手

TCP的三次握手过程是建立TCP连接的过程,其中涉及到SYN、SYN-ACK和ACK三个步骤。

TCP三次握手过程:

第一次握手:客户端向服务器发送一个SYN报文,询问服务器是否打开并准备好接受连接。SYN报文包含客户端的初始序列号。
第二次握手:服务器收到SYN报文后,会向客户端发送一个SYN-ACK报文,确认收到SYN报文并询问客户端是否准备好建立连接。SYN-ACK报文包含服务器的初始序列号。
第三次握手:客户端收到SYN-ACK报文后,会向服务器发送一个ACK报文,确认服务器的SYN-ACK报文。ACK报文包含客户端的初始序列号加1。

上面列出的套接字状态,除了LISTEN和ESTABLISHED是与TCP三次握手过程相关的之外,其他的状态都与TCP连接已经建立后的行为有关。例如,SYN_SENT和SYN_RECV表示连接正在建立过程中,TIME_WAIT和CLOSE_WAIT表示连接已经关闭,但还在等待一些资源释放,FIN_WAIT1和FIN_WAIT2表示一端的连接已经关闭,等待另一端的响应,LAST_ACK表示等待所有剩余的数据包被确认后关闭连接,CLOSED表示连接已经完全关闭。

TCP四次挥手

在TCP连接关闭的过程中,四次挥手(或称四次序列号更新)是一种标准的过程,用于在两个TCP端点之间相互关闭连接。以下是四次挥手的过程:

TCP四次挥手过程:

第一次挥手:当数据传输完成后,主动关闭方(可以是客户端或服务器)会向被动关闭方发送一个FIN报文,告知对方自己已经完成数据发送,将要关闭连接。FIN报文包含主动关闭方的初始序列号加1。
第二次挥手:被动关闭方收到FIN报文后,会向主动关闭方发送一个ACK报文,确认收到FIN报文。ACK报文包含被动关闭方的初始序列号加1。
第三次挥手:被动关闭方发送完ACK报文后,如果此时它也已经完成了数据的发送,那么它也会向主动关闭方发送一个FIN报文,告知对方自己已经完成数据发送,将要关闭连接。FIN报文包含被动关闭方的初始序列号加1。
第四次挥手:主动关闭方收到被动关闭方的FIN报文后,会向被动关闭方发送一个ACK报文,确认收到FIN报文。ACK报文包含主动关闭方的初始序列号加1。


FIN: 当应用层决定关闭连接时,它会通知TCP将数据发送完毕,并发送一个FIN标志位设为1的报文段。这个报文段中通常会包含一个ackno(确认号),表示希望接收对方TCP发送的最后一个ack。
ACK: 接收到FIN报文段后,接收端TCP会发送一个ACK报文段作为应答,确认收到这个FIN报文段。此时,接收端TCP进入CLOSE_WAIT状态。
FIN&ACK: 当发送端TCP收到对FIN报文段的ACK应答后,它知道对端已经准备好关闭连接。因此,发送端TCP发送第二个FIN报文段,表示自己也已经准备好关闭连接。接收端TCP会再次发送ACK报文段进行确认。
LAST_ACK: 最后一个ACK报文段是由发送端TCP发送的,目的是告知接收端TCP,自己已经收到了所有的数据,连接可以完全关闭了。这个ACK报文段通常会携带一个时间戳(例如MSL的数值),以保证在一定时间内能够接收到这个ACK报文段。

在这个过程中,套接字的状态会随之变化。例如,当客户端调用close函数,而服务端没有调用该函数的话,此时服务器就会进入CLOSE_WAIT状态,而客户端则会进入到FIN_WAIT_2状态。这个状态是为了花资源去维护这段连接,等待最后的ACK报文段收到。服务端在接收到最后的ACK报文段后,就会进入TIME_WAIT状态,等待两个MSL的时间才能进入CLOSED状态。这个状态是为了较大概率保证最后一个ACK被服务器收到,避免因为网络延迟等原因导致的数据丢失问题。

因此,套接字的状态与TCP的四次挥手过程密切相关,反映了连接关闭过程中的不同阶段和状态。

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
网络令主要用于网络诊断和测试,以及获取网络信息。常见的网络命令有ping、tracert、nslookup、netstat等。下面简单介绍一下这些命令的使用方法: 1. ping:用于测试网络连接是否通畅,常用于测试网络延迟和丢包情况。使用方法为在命令行中输入“ping 目标IP地址或域名”,例如“ping www.baidu.com”。 2. tracert:用于跟踪数据包在网络上传输的路径,以及检测网络延迟和丢包情况。使用方法为在命令行中输入“tracert 目标IP地址或域名”,例如“tracert www.baidu.com”。 3. nslookup:用于查询域名解析结果,以及测试DNS服务器是否正常工作。使用方法为在命令行中输入“nslookup 域名”,例如“nslookup www.baidu.com”。 4. netstat:用于显示当前网络连接状态和活动进程的网络统计信息。使用方法为在命令行中输入“netstat -a”,可以显示所有活动连接的信息。 至于TCP协议三次握手,它是TCP在建立连接时使用的一种机制,用于确保通信双方的状态同步。具体步骤如下: 1. 客户端向服务器发送SYN报文,表示请求连接。 2. 服务器收到请求后回复一个SYN+ACK报文,表示确认请求并请求连接。 3. 客户端收到服务器的回复后发送一个ACK报文,表示确认连接建立。 这样,连接就建立成功了,双方可以开始通信了。三次握手的目的是为了防止已失效的连接请求报文段突然又传到了服务器,从而导致资源的浪费和混乱。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java编程:架构设计与企业真实项目案例

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值