Go語言實踐_實現一(客戶端)對一(服務器端)聊天室


一、目的

使用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函數可造成程序的堵塞;
  • 網絡中一般是用字節進行數據的傳輸,所以需要進行格式轉換:發送時由字符串轉字節;接收時由字節轉字符串。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM