一、目的
使用Go語言實現一個服務器端與客戶端的聊天室。
軟件:Goland,Go1.9
二、思路
1,首先啟動服務器端,使用listen_socket函數監聽IP地址上的客戶端連接;
2,啟動客戶端,並向服務器端發送數據,發送結束后端口阻塞,等待服務器端的消息;
3,服務器端接收到由客戶端發送來的消息;
4,服務器端向客戶端發送數據,發送結束后;
5,客戶端接收到由服務器端發送來的消息,發送結束后端口阻塞,等待客戶端的消息;
6,重復步驟2-5;
7,如果服務器端接收到由客戶端發送來的“close"消息后,服務器端關閉與客戶端的連接,繼續等待下一個客戶端的連接;
8,客戶端關閉,聊天結束。
三、Go代碼實現
Sever端
// One-to-one ChatRoom Sever package main import ( "fmt" "net" ) //var ConnMap map[string]*net.TCPConn func main() { listen_socket, err := net.Listen("tcp", "127.0.0.1:8000") //打開監聽接口 if err != nil { //如果有錯誤 fmt.Println("sever error") } defer listen_socket.Close() //延遲服務器端關閉 fmt.Println("sever is wating ....") for { conn, err := listen_socket.Accept() //監聽客戶端的端口 if err != nil { fmt.Println("conn fail ...") } fmt.Println("connect client successed") //顯示服務器端連接成功 var msg string //聲明msg為字符串變量 for { //開始接收客戶端發過來的消息 msg = "" //字符串msg初始為空 data := make([]byte, 255) //創建並聲明數據變量,為255位 msg_read, err := conn.Read(data) //接收由客戶端發來的消息,字節賦值給msg_read,err為錯誤 if msg_read == 0 || err != nil { //如果讀取的消息為0字節或者有錯誤 fmt.Println("err") } msg_read_str := string(data[0:msg_read]) //將msg_read_str的字節格式轉化成字符串形式 if msg_read_str == "close" { //如果接收到的客戶端消息為close conn.Write([]byte("close")) break } //fmt.Println(string(data[0:msg_read])) fmt.Println("client say: ", msg_read_str) //接收客戶端發來的信息 fmt.Printf("say to client: ") //提示向客戶端要說的話 fmt.Scan(&msg) //輸入服務器端要對客戶端說的話 //conn.Write([]byte("hello client\n")) //msg_write := []byte(msg) conn.Write([]byte(msg)) //把消息發送給客戶端 //此處造成服務器端的端口堵塞 } fmt.Println("client Close\n") conn.Close() //關閉連接 } }
Client端
// One-to-one ChatRoom Client package main import ( "fmt" "net" ) func main() { conn, err := net.Dial("tcp", "127.0.0.1:8000") if err != nil { fmt.Println("conn fail...") } defer conn.Close() fmt.Println("connect sever successed") var msg string //聲明msg為字符串變量 for { msg = "" //初始化msg為空值 fmt.Printf("say to sever: ") fmt.Scan(&msg) //輸入客戶端向服務器端要發送的消息 //fmt.Println(msg) //msg_write := []byte(msg) //conn.Write(msg_write) conn.Write([]byte(msg)) //信息轉化成字節流形式並向服務器端發送 //此處造成客戶端程序端口堵塞 //fmt.Println([]byte(msg)) //等待服務器端發送信息回來 data := make([]byte, 255) msg_read, err := conn.Read(data) if msg_read == 0 || err != nil { fmt.Println("err") } msg_read_str := string(data[0:msg_read]) if msg_read_str == "close" { conn.Write([]byte("close")) break } fmt.Println("sever say:", msg_read_str) } conn.Close() }
四、小結
- Write、Read、conn、Scan函數可造成程序的堵塞;
- 網絡中一般是用字節進行數據的傳輸,所以需要進行格式轉換:發送時由字符串轉字節;接收時由字節轉字符串。