Socket TCP 使用入门
Socket TCP 使用入门
TCP 通信协议
-
网络通信的状态
- LISTENING - 表示正在监听传入连接的端口。
- ESTABLISHED - 表示已经建立连接的正常数据传输状态。
- CLOSE_WAIT - 表示本地已经完成数据传输,正在等待关闭连接。
- TIME_WAIT - 表示连接已经关闭,但是仍在等待一段时间以确保所有传输的数据都被清理和确认。
- SYN_SENT - 表示正在尝试建立传出连接的初始状态,等待对方确认。
- SYN_RECEIVED - 表示收到对方的连接请求(SYN)并发送了确认请求(ACK)。
- FIN_WAIT_1 - 表示已经发送了连接关闭请求(FIN)并等待对方确认。
- FIN_WAIT_2 - 表示已接收到对方的关闭请求(FIN)并发送了确认(ACK)。
- CLOSING - 表示在关闭连接期间遇到了问题或发生了错误。
- LAST_ACK - 表示已发送连接关闭请求(FIN)并收到了对方的确认(ACK),等待最后的关闭确认。
- CLOSED - 表示连接已经完全关闭或未打开。
可使用命令netstat -nao命令查看计算机进程映射的端口
-
三次握手
- 第一次
客户端发送一个 SYN 包给服务端 - 第二次
服务端接收到数据后,返回一个 SYN-ACK 包给客户端 - 第三次
客户端接收到数据后,返回一个 ACK 包给服务端
- 第一次
客户端 服务器
init -> SYN listen 客户端发送一个请求连接的 syn 包 1次
syn-send SYN+ACK <- listen 服务端返回一个 syn+ack 包 2次
syn-send -> ACK syn-rcvd 客户端返回一个 ack 包 3次
为什么是三次而不是两次?
服务端回复 syn+ack 后就建立连接,防止已经失效的请求报文突然又传到服务器引起错误。
例如:客户端发送 syn 包产生滞留情况。
- 四次挥手
- 第一次
客户端发送 FIN 包给服务端 - 第二次
服务端接收到数据后,返回 ACK 包给客户端 - 第三次
服务端发送 FIN 包给客户端 - 第四次
客户端接收到数据后,返回 ACK 包给服务端
- 第一次
客户端 服务器
established -> FIN established 客户端发送 final 包 1次
fin-wait-1 ACK <- Close-Wait 服务端返回 ack 包 2次
此时服务端还可发送未发送的数据,客户端也还可以接收数据。
fin-wait-2 FIN <- Close-Wait 服务端发送一个 fin 包 3次
fin-wait-2 -> ACK Last-Ack 4次
客户端发送 ack 后进入超时等待状态 ,而服务端接收到 ack 包后立刻关闭。
time-wait Closed
Closed
为什么4次挥手后要进入超时等待?
客户端发送 ack 包之后,如果服务端没有接收到 ack, 那么服务端会再发送 fin 包,客户端接收到之后重新
刷新 time-wait 时间。
进行可靠的断开连接确认。
使用 SOCKET 通信
服务端和客户端
如何确定服务端客户端?
通常发起请求的一段作为客户端,响应请求的一端作为服务端。
- 创建服务端
var server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 服务端绑定到 IP 和 端口
server.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 65535));
// 开启监听
server.Listen();
// 等待客户端连接
Socket client = server.Accept();
// 我们使用 client 与客户端进行 TCP 通信。
- 客户端连接到服务器
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 连接服务端
socket.Connect("127.0.0.1", 65535);
通信模式
- 同步模式
我们使用不带 Async、Begain、End 类似这种方法进行 TCP 通信的模式为同步模式。
例如 BeginAccept(),ReceiveAsync(arg)这些方法是异步的
而 Accept()、Receive(buffer)这些方法是同步的
// 阻塞接收数据,如果设置超时,可能会抛超时异常
var size = socket.Receive(buffer);
- 异步模式
-
APM 异步模式
// 开启一个异步接收5个字节 var resulr = socket.BeginReceive(buffer, 0, 5, SocketFlags.None, (arg) => { Console.WriteLine("接受完成回调!"); }, null); // 阻塞等待接收完成,最多只接收5个字节 var size = socket.EndReceive(resulr); -
EAP 异步模式
var arg = new SocketAsyncEventArgs(); arg.Completed += Arg_Completed; socket.ReceiveAsync(arg); // 通过这种方式,还可以判断 TCP 另一端是否请求断开连接。 private static void Arg_Completed(object? sender, SocketAsyncEventArgs e) { if (e.SocketError == SocketError.Success) { if (e.Buffer?.Length > 0) Console.WriteLine(Encoding.UTF8.GetString(e.Buffer)); } }
-
浙公网安备 33010602011771号