Go-网络编程(TCP)
Go中提供了网络编程接口支持HTTP、TCP、UDP协议等,下面演示下TCP通信Server、Client
Server
package main
import (
"fmt"
"net"
)
func main() {
// 创建一个 TCP 监听器
listener, err := net.Listen("tcp", "127.0.0.1:9000")
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Server listening on port 9000")
// 循环监听客户端连接请求
for {
conn, err := listener.Accept()
if err != nil {
fmt.Println("Error:", err)
continue
}
// 处理客户端连接请求
go handleConnection(conn)
}
}
func handleConnection(conn net.Conn) {
defer conn.Close()
// 读取客户端发送的数据
buf := make([]byte, 1024)
n, err := conn.Read(buf)
if err != nil {
fmt.Println("Error:", err)
return
}
// 处理客户端发送的数据
data := buf[:n]
fmt.Println("Received data: ", string(data))
// 发送响应数据给客户端
response := "Hello, client! 我是Server,Over"
conn.Write([]byte(response))
}
Client
package main
import (
"fmt"
"net"
)
func main() {
// 连接服务器
conn, err := net.Dial("tcp", "127.0.0.1:9000")
if err != nil {
fmt.Println("Error:", err)
return
}
// 发送数据给服务器
message := "Hello, server! 我是Client"
conn.Write([]byte(message))
// 读取服务器响应数据
buf := make([]byte, 1024)
n, err := conn.Read(buf)
if err != nil {
fmt.Println("Error:", err)
return
}
// 处理服务器响应数据
data := buf[:n]
fmt.Println("Received data: ", string(data))
conn.Close()
}
运行
- 客户端不断发送请求
- 服务端读取请求
- 服务端处理请求
- 服务端写回响应
Server run
Client run
Client发起请求,收到Server的相应
Wireshark分析
使用Wireshark工具分析下请求响应的流程
tcp.port == 9000 and ip.addr == 127.0.0.1
上图是这是Server、Client之间的本地回环通信(Loopback),源和目标IP地址均为127.0.0.1,因此这些包不会离开本地主机。下面是每个TCP报文段的解释:
- 10252:系统为Client动态随机分配的端口
- 9000:Server的端口
-
第339号数据包:Client向Server发送SYN请求连接,seq=0,win=65535,mss=65495,ws=256,sack_perm,表示客户端请求建立连接,并发送了自己的窗口大小、最大分段大小、窗口扩展、SACK_PERM等信息给Server。
-
第340号数据包:Server响应Client的SYN请求,ack=1,win=65535,mss=65495,ws=256,sack_perm,表示服务端接收到了客户端的请求,并发送了自己的窗口大小、最大分段大小、窗口扩展、SACK_PERM等信息给Client。
-
第341号数据包:Client确认Server的SYN,ACK响应,seq=1,ack=1,win=2161152,表示客户端接收到了服务端的响应,并发送了自己的序列号、确认号和窗口大小给Server。
-
第342号数据包:Client向Server发送数据,seq=1,ack=1,win=2161152,len=27,表示客户端向服务端发送了长度为27的数据,并发送了自己的序列号、确认号和窗口大小给Server。
-
第343号数据包:Server对Client发送的数据进行确认,seq=1,ack=28,win=2161152,表示服务端接收到了客户端发送的数据,并发送了自己的确认号和窗口大小给Client。
-
第344号数据包:Server向Client发送数据,seq=1,ack=28,win=2161152,len=32,表示服务端向客户端发送了长度为32的数据,并发送了自己的序列号、确认号和窗口大小给Client。
-
第345号数据包:Client对Server发送的数据进行确认,seq=28,ack=33,win=2161152,表示客户端接收到了服务端发送的数据,并发送了自己的确认号和窗口大小给Server。
-
第346号数据包:Server向Client发送FIN,ACK关闭连接,seq=33,ack=28,win=2161152,len=0,表示服务端发送了FIN和ACK标志位,表示将关闭连接,并发送了自己的序列号、确认号和窗口大小给Client。
-
第347号数据包:Client对Server的FIN,ACK响应进行确认,seq=28,ack=34,win=2161152,表示客户端接收到了服务端的FIN和ACK标志位,并发送了自己的确认号和窗口大小给Server。
-
第348号数据包:Client向Server发送FIN,ACK关闭连接,seq=28,ack=34,win=2161152,len=0,表示客户端发送了FIN和ACK标志位,表示将关闭连接,并发送了自己的序列号、确认号和窗口大小给Server。
-
第349号数据包:Server对Client的FIN,ACK响应进行确认,seq=34,ack=29,win=2161152,表示服务端接收到了客户端发送的FIN和ACK标志位,并发送了自己的确认号和窗口大小给Client。
参数解释:
-
seq:序列号,用于标识每个TCP报文段中的数据字节流,是发送方维护的一个32位无符号整数,用于保证TCP数据可靠传输,表示本报文段中首个数据字节的序号。
-
ack:确认号,用于对序列号的确认,是对方期望接收到的下一个TCP报文段的第一个字节的序号,也是本报文段中确认的数据字节序号。
-
win:窗口大小,表示接收方还能够接收多少字节的数据,是接收方用于控制发送方发送速度的一个参数,由接收方通过ACK报文向发送方通知。
-
mss:最大分段大小,是指TCP报文段中的数据部分的最大长度,是发送方和接收方通过协商确定的,一般是两端协商后支持的最大MTU减去TCP报头的长度。
-
ws:窗口扩展,是TCP连接中的一种可选参数,表示TCP窗口大小的扩展,用于提高传输效率,可选参数值为0-14,表示窗口大小扩展的因子。
-
sack_perm:是TCP连接中的一种可选参数,表示是否启用SACK(Selective Acknowledgment,选择性确认)选项,如果启用,则可以提高TCP数据传输的可靠性和效率,但会增加数据包大小。
-
len:数据长度,是指TCP报文段中数据部分的长度,不包括TCP报头和选项部分的长度。
在TCP通信中,常见的标志位有以下几个:
- SYN:同步序列号,用于建立一个新的TCP连接。
- ACK:确认序号,用于确认收到的数据。
- PSH:推送数据,用于传输数据前通知对方尽快处理。
- FIN:结束通信,用于终止一个TCP连接。
具体来说:
- SYN:SYN标志用于建立一个新的TCP连接。TCP协议使用“三次握手”来确保连接的可靠性,其中SYN标志用于表示客户端请求连接,服务端在收到请求后会发送SYN+ACK标志,用于表示接收请求并确认连接。客户端再发送一次ACK标志,用于确认服务端的SYN+ACK。这个过程中,客户端和服务端的序列号都会发送一些初始值。
- ACK:ACK标志主要用于确认收到的数据。在TCP通信中,接收方一般会返回一个ACK标志,用于告诉对方收到了数据。ACK标志也可以用于确认已经成功建立了一个TCP连接。
- PSH:PSH标志用于通知接收方立即处理数据,不进行数据缓存。在传输一些实时性要求高的数据时,可以使用PSH标志来加快数据的传输速度。
- FIN:FIN标志用于结束一个TCP连接。TCP通信中的连接是双向传输的,因此FIN标志可以由客户端或服务端发起,用于终止连接。当一方发送了FIN标志之后,另一方会发送一个ACK标志,然后也发送一个FIN标志,最终关闭连接。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南