服务端代码:

package main

import (
	"bufio"
	"errors"
	"flag"
	"fmt"
	"net"
	"os"
	"strconv"
)



// 指定一个命令行参数的名字
var port int
func Init() {
	flag.IntVar(&port, "port", 8081, "set your server port")
}

func main() {
	// 初始化命令行变量
	Init()
	flag.Parse()

	// 监听端口
	portStr := strconv.Itoa(port)
	if portStr == "" {
		fmt.Println("端口不正确,请确认")
		return
	}

	listen, err := net.Listen("tcp", ":" + portStr)
	if err != nil {
		fmt.Println("监听端口" + portStr + "失败", err)
	}
	fmt.Println("监听" + portStr + "成功!")
	for {
		// 等待连接
		conn, err := listen.Accept()
		if err != nil {
			fmt.Println("建立连接失败了")
		}
		fmt.Println("建立连接成功了")

		// STEP - 1 处理发送消息
		go func(conn net.Conn) {
			handleSend(conn)
		}(conn)

		// STEP - 2 处理接收消息
		// 必须要这个for 保持程序一直处于唤醒状态,一直读取conn里面的流
        var receiveError error
		for {
			//go func(conn net.Conn) {
				receiveError= handleReceive(conn)
				if receiveError !=nil {
					break
				}
			//}(conn)
		}
		if receiveError != nil {
			break
		}
	}

}


func handleReceive(conn net.Conn)  error{
	//fmt.Println("handleReceive Method")
	buff := make([]byte, 4096)
	cnt, err := conn.Read(buff)
	if cnt == 0 || err != nil {
		fmt.Println("[WARN]-----断开连接------")
		fmt.Println("[WARN]------END--------")
		return errors.New("连接错误")
	}
	receiveData := string(buff)
	fmt.Println("你收到了消息:", receiveData)
	return nil
}

func handleSend(conn net.Conn) {
	// 读取命令行里面的字符
	//fmt.Println("handleSend Method")
	r := bufio.NewReader(os.Stdin)
	var line string
	for {
		fmt.Println("Send Message->")
		rawLineBytes, _, _ := r.ReadLine()
		line = string(rawLineBytes)
		if len(line) < 1 {
			continue
		}
		// 发送
		fmt.Println("你发送了数据: [YOU]:" + line)
		//conn.Write([]byte("[SERVER]:  " + line))
		_, err := fmt.Fprintf(conn, "[SERVER]:  " + line)
		if err != nil {
			fmt.Println("发送数据失败")
		}
	}
}


启动代码:

```go
go run main.go -port=8081 

客户端代码:

package main

import (
	"bufio"
	"errors"
	"flag"
	"fmt"
	"io"
	"net"
	"os"
	"time"
)

var serverPort int
var serverIP string
func Init() {
	flag.IntVar(&serverPort, "serverPort", 8081, "set the server PORT you connect with")
	flag.StringVar(&serverIP, "serverIP", "127.0.0.1", "set the server IP you will connect with")
}

func main() {
	// 初始化命令行参数
	Init()
	flag.Parse()

	// 连接server端
	serverAddress := fmt.Sprintf("%s:%d", serverIP, serverPort)
	conn, err := net.DialTimeout("tcp", serverAddress, time.Second * 3)

	// 连接失败
	if err != nil {
		fmt.Println(fmt.Sprintf("连接[%s]失败了", serverAddress))
		return
	}
	// 连接成功
	fmt.Println(fmt.Sprintf("建立连接成功了[%s] !", serverAddress))

	// 往conn这个写一个消息
	fmt.Fprintf(conn, "HEAD / HTTP/1.0\r\n\r\n")


	// STEP - 1 处理发送消息
     go func(conn net.Conn) {
		 handleSend(conn)
	 }(conn)

	// STEP - 2 处理接收消息
	// 必须要这个for 保持程序一直处于唤醒状态,一直读取conn里面的流
	for {
		err := handleReceive(conn)
		if err != nil {
			break
		}
	}
}


func handleReceive(conn net.Conn) error {
	//fmt.Println("handleReceive Method")
	buff := make([]byte, 4096)
	cnt, err := conn.Read(buff)
	// 收到的数据长度为0
	//if cnt == 0 || err != nil {
	if  err != nil {
		fmt.Println("断开连接")
		fmt.Println("----------END-----------")
		fmt.Println(err, cnt, err == io.EOF)
		return errors.New("断开连接了")
	}
	fmt.Println("你收到了消息:", string(buff))
	return nil
}

func handleSend(conn net.Conn)  {
	//fmt.Println("handleSend Method")
	r := bufio.NewReader(os.Stdin)
	var line string
	for {
		fmt.Println("Send Message->")
		rawLineBytes, _, _ := r.ReadLine()
		line = string(rawLineBytes)
		if len(line) < 1 {
			continue
		}
		fmt.Println("你发送了数据: [YOU]:" + line)
		_, err := fmt.Fprintf(conn, "[CLIENT]:  " + line)
		if cnt == 0||err != nil {
			fmt.Println("发送数据失败")
		}
	}
}

启动代码:

	go run main.go -serverPort=8081 -serverIp=127.0.0.1

tips:

1, 这个简单的网络应用有几个关键点
     A : for 循环 等待连接/ 等待用户从命令行输入
     B :go routine 协程处理发送或者接受消息,因为这两个动作,都是需要程序block住,所以必须 要用go routine

2,注意启动的时候端口占用情况,也许8081被占用

3,go build 的时候,windows/mac/linux平台有不同的命令。(自行搜索下