TCP状态转换图:
主动发起连接请求端: CLOSED —— 完成三次握手 —— ESTABLISEHED(数据通信状态)—— Dial()函数返回
被动发起连接请求端: CLOSED —— 调用Accept()函数 —— LISTEN —— 完成三次握手 —— ESTABLISEHED (数据通信状态)—— Accept()函数返回
数据传递期间 —— ESTABLISEHED (数据通信状态)
主动关闭连接请求端:
ESTABLISEHED —— FIN_WAIT_2 (半关闭)—— TIME_WAIT —— 2MSL —— 确认最后一个ACK被对端成功接收。—— CLOSE
半关闭、TIME_WAIT、2MSL ——只会出现在 “主动关闭连接请求端”
被动关闭连接请求端:ESTABLISEHED —— CLOSE

查看状态命令:
windows:netstat -an | findstr 8001(端口号)
Linux: netstat -apn | grep 8001
TCP-CS并发服务器:
1. 创建 监听套接字 listener := net.Listen("tcp", 服务器的IP+port) // tcp 不能大写
2. defer listener.Close()
3. for 循环 阻塞监听 客户端连接事件 conn := listener.Accept()
4. 创建 go程 对应每一个 客户端进行数据通信 go HandlerConnet()
5. 实现 HandlerConnet(conn net.Conn)
1) defer conn.Close()
2) 获取成功连接的客户端 Addr conn.RemoteAddr()
3) for 循环 读取 客户端发送数据 conn.Read(buf)
4) 处理数据 小写 —— 大写 strings.ToUpper()
5)回写转化后的数据 conn.Write(buf[:n])
func HandlerConnect(conn net.Conn) {
defer conn.Close()
// 获取连接的客户端 Addr
addr := conn.RemoteAddr()
fmt.Println(addr, "客户端成功连接!")
// 循环读取客户端发送数据
buf := make([]byte, 4096)
for {
n, err := conn.Read(buf)
//fmt.Println(buf[:n])
if "exit\n" == string(buf[:n]) || "exit\r\n" == string(buf[:n]) {
fmt.Println("服务器接收的客户端退出请求,服务器关闭")
return
}
if n == 0 {
fmt.Println("服务器检测到客户端已关闭,断开连接!!!")
return
}
if err != nil {
fmt.Println("conn.Read err:", err)
return
}
fmt.Println("服务器读到数据:", string(buf[:n])) // 使用数据
// 小写转大写,回发给客户端
conn.Write([]byte(strings.ToUpper(string(buf[:n]))))
}
}
func main() {
// 创建监听套接字
//listener, err := net.Listen("tcp", "127.0.0.1:8001")
listener, err := net.Listen("tcp", "192.168.15.78:8001")
if err != nil {
fmt.Println("net.Listen err:", err)
return
}
defer listener.Close()
// 监听客户端连接请求
for {
fmt.Println("服务器等待客户端连接...")
conn, err := listener.Accept()
if err != nil {
fmt.Println("listener.Accept err:", err)
return
}
// 具体完成服务器和客户端的数据通信
go HandlerConnect(conn)
}
}
TCP-CS并发客户端:
1. 匿名 go 程 , 获取 键盘输入, 写给服务器
2. for 循环读取服务器回发数据
发送数据时,默认在结尾自带‘ \r\n ’
func main() {
// 主动发起连接请求
conn, err := net.Dial("tcp", "192.168.15.78:8001")
if err != nil {
fmt.Println("net.Dial err:", err)
return
}
defer conn.Close()
// 获取用户键盘输入( stdin ),将输入数据发送给服务器
go func() {
str := make([]byte, 4096)
for {
n, err := os.Stdin.Read(str)
if err != nil {
fmt.Println("os.Stdin.Read err:", err)
continue
}
//写给服务器, 读多少,写多少!
conn.Write(str[:n])
}
}()
// 回显服务器回发的大写数据
buf := make([]byte, 4096)
for {
n, err := conn.Read(buf)
if n == 0 {
fmt.Println("检查到服务器关闭,客户端也关闭")
return
}
if err != nil {
fmt.Println("conn.Read err:", err)
return
}
fmt.Println("客户端读到服务器回发:", string(buf[:n]))
}
}