1 要求
- 1)編寫一個服務端程序,監聽8888端口
- 2)可以和多個客戶端創建連接(goroutine)
- 3)連接成功,客戶端可以發送數據,服務端接收數據,並顯示在終端上
- 4)能通過終端輸入數據(一行一行發送),併發送給服務器
- 5)在終端輸入exit,表示退出程序
2 C/S端處理流程
服務端的處理流程
- 1)監聽端口 8888
- 2)接收客戶端的tcp連接,建立客戶端和服務端的連接
- 3)創建goroutine,處理該連接的請求(通常客戶端會通過連接發送請求包)
客戶端的處理流程
- 1)建立與服務器端的連接
- 2)發送請求數據,接收服務器端返回的結果數據
- 3)關閉連接
要用到net包,官方文檔參考:
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)
}
}
}