Go is one of the main objectives for large-scale back-end service program, this is a network communications server program is essential to a key part.
Network programming in two ways:
(1) TCP Socket Programming: mainstream network programming, was called TCP Socket programming, because the bottom is based on TCP / IP protocols;
(2) Programming http B / S structure, when using the browser to access the server, the http protocol is used, the http tcp socket bottom is achieved;
Communication between computers need, must have a network cable, network card or wireless network card;
TCP / IP model: an application layer, transport layer, network layer, data link layer, physical layer;
IP address: hosts and routers on the internet has an ip address each, which comprises a network number and host number, ip address has ipv4 (32 bit) or ipv6 (128 bits) can be viewed Ipconfig.
Port: The port, especially tcp / ip protocol on the logical sense of the port. Total 256 × 256-1 = 65535 ports;
Port Category:
- 0 is reserved port;
- 1-1024 is a fixed-port (22: ssh remote login protocol, 23: telnet use, 21: ftp use, 25: smtp service use, 80: lis use, 7: echo service)
- 1025-65535: a dynamic port, for programmers to use;
A block diagram of the communication between the server and the client:
As can be seen, the communication between them is by port (because it is simple communications, the current client does not communicate directly, only through the client)
server.go
package main import ( "fmt" "net" ) func process(conn net.Conn) { //这里接受客户端的数据 defer conn.Close() for { //创建一个新的切片 buf := make([]byte, 1024) //等待客户端发送信息,如果客户端没发送,协程就阻塞在这 // fmt.Printf("服务器在等待客户端%v的输入\n", conn.RemoteAddr().String()) n, err := conn.Read(buf) if err != nil { // fmt.Println("服务器read err=", err) fmt.Println("客户端退出了") return } //显示客户端发送内容到服务器的终端 fmt.Print(string(buf[:n]) + "\n") } } func main() { fmt.Println("服务器开始监听...") //协议、端口 listen, err := net.Listen("tcp", "0.0.0.0:8888") if err != nil { fmt.Println("监听失败,err=", err) return } //延时关闭 defer listen.Close() for { //循环等待客户端连接 fmt.Println("等待客户端连接...") conn, err := listen.Accept() if err != nil { fmt.Println("Accept() err=", err) } else { fmt.Printf("Accept() suc con=%v,客户端Ip=%v\n", conn, conn.RemoteAddr().String()) } //这里准备起个协程为客户端服务 go process(conn) } //fmt.Printf("监听成功,suv=%v\n", listen) }
client.go
package main import ( "bufio" "fmt" "net" "os" "strings" ) func main() { //同样是tcp协议,192.168.1.145服务端的ip地址,这里是我自己本机的地址,可在终端用ipconfig查看,后面是服务端开启的端口号 conn, err := net.Dial("tcp", "192.168.1.145:8888") if err != nil { fmt.Println("client dial err=", err) return } //哭护短在命令行输入单行数据 reader := bufio.NewReader(os.Stdin) for { //从终端读取一行用户的输入,并发给服务器 line, err := reader.ReadString('\n') if err != nil { fmt.Println("readString err=", err) } //去掉输入后的换行符 line = strings.Trim(line, "\r\n") //如果是exit,则退出客户端 if line == "exit" { fmt.Println("客户端退出了") break } //将line发送给服务器 _, e := conn.Write([]byte(line)) if e != nil { fmt.Println("conn.write err=", e) } // fmt.Printf("客户端发送了%d字节的数据,并退出", n) } }
首先在一个终端打开服务器:
然后连接两个客户端:
注意到,每个客户端的端口号是不一致的:
然后两个客户端分别发送消息给服务端:
服务端可以接收到信息:
最后输入exit分别关闭两个客户端:
两个客户端都退出了,然后服务端继续等待新的客户端的连接。