七、Golang网络编程:TCP状态转换和并发TCP-CS代码实现

TCP状态转换图:

主动发起连接请求端: CLOSED —— 完成三次握手 —— ESTABLISEHED(数据通信状态)—— Dial()函数返回

被动发起连接请求端: CLOSED —— 调用Accept()函数 —— LISTEN —— 完成三次握手 —— ESTABLISEHED (数据通信状态)—— Accept()函数返回

	数据传递期间 —— ESTABLISEHED (数据通信状态)

主动关闭连接请求端:

	ESTABLISEHED —— FIN_WAIT_2 (半关闭)——  TIME_WAIT —— 2MSL —— 确认最后一个ACK被对端成功接收。—— CLOSE

	半关闭、TIME_WAIT、2MSL ——只会出现在 “主动关闭连接请求端”

被动关闭连接请求端:ESTABLISEHED —— CLOSE

TCP状态转换

查看状态命令:

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]))
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值