(十一)TCP网络编程小案例

1 要求

  • 1)编写一个服务端程序,监听8888端口
  • 2)可以和多个客户端创建连接(goroutine)
  • 3)连接成功,客户端可以发送数据,服务端接收数据,并显示在终端上
  • 4)能通过终端输入数据(一行一行发送),并发送给服务器
  • 5)在终端输入exit,表示退出程序

2 C/S端处理流程

服务端的处理流程

  • 1)监听端口 8888
  • 2)接收客户端的tcp连接,建立客户端和服务端的连接
  • 3)创建goroutine,处理该连接的请求(通常客户端会通过连接发送请求包)

客户端的处理流程

  • 1)建立与服务器端的连接
  • 2)发送请求数据,接收服务器端返回的结果数据
  • 3)关闭连接

要用到net包,官方文档参考:

Go语言标准库文档中文版

3 代码实现

3.1 Server端

package main

import (
	"fmt"
	"net"
)

func process(conn net.Conn)  {

	// 这里我们循环的接收客户端发送的数据
	defer conn.Close()  // 关闭连接

	for {
		// 创建一个切片,用于存放接收客户端发送过来的数据
		buf := make([]byte, 1024)
		
		// 1.等待客户端通过conn发送信息
		// 2.如果客户端没有write[发送],那么协程就阻塞在这里
		// fmt.Printf("服务器在等待客户端%s 发送信息\n", conn.RemoteAddr().String())
		n, err := conn.Read(buf)  // 从conn读取数据 Read接收测参数的是一个切片
		if err != nil {
			fmt.Printf("客户端 %s 已退出.\n", conn.RemoteAddr().String())
			return
		}

		// 3.显示客户端发送了 %d 字节的数据
		fmt.Print(string(buf[:n]))  // 一定要把n给切片处理下,不然会出输出很长的内容

	}

}

func main() {

	fmt.Println("服务器开始监听...")

	listen, err := net.Listen("tcp", "0.0.0.0:8888")  // 在本地监听8888端口
	if err != nil {
		fmt.Println("listen err = ", err)
		return
	}

	defer listen.Close()  // 关闭监听端口

	// 循环等待客户端接入
	for {
		// 等待客户端连接
		fmt.Println("等待客户端来连接...")
		conn, err := listen.Accept()
		if err != nil {
			fmt.Println("Accept() err=", err)
		} else {
			// 显示客户端ip conn.RemoteAddr().String()
			fmt.Printf("Client connected successfully, Client_IP = %v\n", conn.RemoteAddr().String())
		}
		
		// 这里准备起一个协程,为多个客户端服务
		go process(conn)
	}
	fmt.Printf("listen suc= %v ", listen)
}

3.2 Client端

package main

import (
	"fmt"
	"net"
	"bufio"
	"os"
	"strings"
)

func main() {

	// 连接服务端

	conn, err := net.Dial("tcp", "127.0.0.1:8888")
	if err != nil {
		fmt.Printf("client dial failed err = %v", err)
		return
	}
	//fmt.Println("conn=", conn)

	// 客户端往服务端发送单行数据,然后就退出
	// 客户端在终端输入一句话
	reader := bufio.NewReader(os.Stdin)  // os.Stdin 代表标准输入,即终端

	for {
		// 从终端读取一行用户输入,并准备发送给服务器
		line, err := reader.ReadString('\n')
		if err != nil {
			fmt.Println("readstring err = ", err)
		}

		// 如果用户输入的是exit就退出
		line = strings.Trim(line, " \r\n")
		if line == "exit" {
			fmt.Println("客户端退出...")
			break
		}

		// 再将line 发送给服务器
		_, err = conn.Write([]byte(line + "\n"))
		if err != nil {
			fmt.Println("conn.Write err = ", err)
		}
	}

}

你可能感兴趣的:(Golang)