Golang聊天室

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
  • 前期準備
    • 需要 import "net"包
    • IP 類型,其中一個重要的方法是 IP.ParseIP(ipaddr string)來判斷是否是合法的 IP 位址
  • TCP Client
    • func (c *TCPConn) Write(b []byte) (n int, err os.Error)用於發送資料,返回傳送的資料長度或者返回錯誤,是TCPConn的方法
    • func (c *TCPConn) Read(b []byte) (n int, err os.Error)用於接收資料,返回接收的長度或者返回錯誤,是 TCPConn 的方法
    • TCPAddr 類型,儲存 TCP 的地址資訊,包括地址和連接埠
      type TCPAddr struct {  IP IP  Port int}
    • func ResolveTCPAddr(net, addr string) (*TCPAddr, os.Error)擷取一個 TCPAddr,參數都是 string 類型,net 是個 const string,包括 tcp4,tcp6,tcp 一般使用 tcp,相容 v4 和 v6,addr 表示 ip 地址,包括連接埠號碼,如www.google.com:80之類的
    • func DialTCP(net string, laddr, raddr *TCPAddr) (c *TCPConn, err os.Error)用來串連(connect)到遠程伺服器上,net 表示協議方式,tcp,tcp4 或者 tcp6,laddr 表示本機地址,一般為 nil,raddr 表示遠程地址,這裡的 laddr 和 raddr 都是 TCPAddr 類型的,一般是上一個函數的傳回值。
    • 作為一個 TCP 的用戶端,基本的操作流程如下:
      service="www.google.com:80"tcpAddr, err := net.ResolveTCPAddr("tcp4", service)conn, err := net.DialTCP("tcp", nil, tcpAddr)_, err = conn.Write([]byte("HEAD / HTTP/1.0\r\n\r\n"))_, err = conn.Read(b) / result, err := ioutil.ReadAll(conn)
  • TCP Server
    • func ListenTCP(net string, laddr *TCPAddr) (l *TCPListener, err os.Error)用來監聽連接埠,net 表示協議類型,laddr 表示本機地址,是 TCPAddr 類型,注意,此處的 laddr 包括連接埠,返回一個*TCPListener類型或者錯誤
    • func (l *TCPListener) Accept() (c Conn, err os.Error)用來返回一個新的串連,進行後續操作,這是 TCPListener 的方法,一般 TCPListener 從上一個函數返回得來。
    • 伺服器的基本操作流程為:
      service:=":9090"tcpAddr, err := net.ResolveTCPAddr("tcp4", service)l,err := net.ListenTCP("tcp",tcpAddr)conn,err := l.Accept()go Handler(conn) //此處使用go關鍵字建立線程處理串連,實現並發
  • 實現一個公用聊天伺服器。
    • 伺服器接收用戶端的資訊
    • 接收完以後將用戶端的資訊發送到所有的用戶端上
    • 用戶端使用/quit退出聊天
    • 只使用一套代碼,通過命令列參數啟動伺服器還是用戶端
  • 主要知識點如下:

    1. 代碼中包括了伺服器和用戶端的內容,如果是伺服器,直接輸入./chat server 9090即可,用戶端也很簡單,輸入./chat client :9090就好;
    2. 如果是用戶端,其實就包括了兩部分內容,一部分是 chatSend 函數,接受使用者的輸入;另一部分是connect 到 server,接受相關資訊;
    3. 如果是 server,稍微複雜一點,有三個部分組成。第一部分就是不停地 accept 各個用戶端;第二個就是為每一個用戶端創立 Handler 函數,接受用戶端發來的資訊;第三個就是 echoHandler 函數,它的作用就是將從某一使用者接受過來的資訊廣播給其他所有的用戶端,就是這麼簡單。
      [實現]

         package main   import (       "fmt"       "net"       "os"   )   ////////////////////////////////////////////////////////   //   //錯誤檢查   //   ////////////////////////////////////////////////////////   func checkError(err error, info string) (res bool) {       if err != nil {           fmt.Println(info + "  " + err.Error())           return false       }       return true   }   ////////////////////////////////////////////////////////   //   //伺服器端接收資料線程   //參數:   //      資料連線 conn   //      通訊通道 messages   //   ////////////////////////////////////////////////////////   func Handler(conn net.Conn, messages chan string) {       fmt.Println("connection is connected from ...", conn.RemoteAddr().String())       buf := make([]byte, 1024)       for {           lenght, err := conn.Read(buf)           if checkError(err, "Connection") == false {               conn.Close()               break           }           if lenght > 0 {               buf[lenght] = 0           }           //fmt.Println("Rec[",conn.RemoteAddr().String(),"] Say :" ,string(buf[0:lenght]))           reciveStr := string(buf[0:lenght])           messages <- reciveStr       }   }   ////////////////////////////////////////////////////////   //   //伺服器發送資料的線程   //   //參數   //      串連字典 conns   //      資料通道 messages   //   ////////////////////////////////////////////////////////   func echoHandler(conns *map[string]net.Conn, messages chan string) {       for {           msg := <-messages           fmt.Println(msg)           for key, value := range *conns {               fmt.Println("connection is connected from ...", key)               _, err := value.Write([]byte(msg))               if err != nil {                   fmt.Println(err.Error())                   delete(*conns, key)               }           }       }   }   ////////////////////////////////////////////////////////   //   //啟動伺服器   //參數   //  連接埠 port   //   ////////////////////////////////////////////////////////   func StartServer(port string) {       service := ":" + port //strconv.Itoa(port);       tcpAddr, err := net.ResolveTCPAddr("tcp4", service)       checkError(err, "ResolveTCPAddr")       l, err := net.ListenTCP("tcp", tcpAddr)       checkError(err, "ListenTCP")       conns := make(map[string]net.Conn)       messages := make(chan string, 10)       //啟動伺服器廣播線程       go echoHandler(&conns, messages)       for {           fmt.Println("Listening ...")           conn, err := l.Accept()           checkError(err, "Accept")           fmt.Println("Accepting ...")           conns[conn.RemoteAddr().String()] = conn           //啟動一個新線程           go Handler(conn, messages)       }   }   ////////////////////////////////////////////////////////   //   //用戶端發送線程   //參數   //      發送串連 conn   //   ////////////////////////////////////////////////////////   func chatSend(conn net.Conn) {       var input string       username := conn.LocalAddr().String()       for {           fmt.Scanln(&input)           if input == "/quit" {               fmt.Println("ByeBye..")               conn.Close()               os.Exit(0)           }           lens, err := conn.Write([]byte(username + " Say :::" + input))           fmt.Println(lens)           if err != nil {               fmt.Println(err.Error())               conn.Close()               break           }       }   }   ////////////////////////////////////////////////////////   //   //用戶端啟動函數   //參數   //      遠程ip地址和連接埠 tcpaddr   //   ////////////////////////////////////////////////////////   func StartClient(tcpaddr string) {       tcpAddr, err := net.ResolveTCPAddr("tcp4", tcpaddr)       checkError(err, "ResolveTCPAddr")       conn, err := net.DialTCP("tcp", nil, tcpAddr)       checkError(err, "DialTCP")       //啟動用戶端發送線程       go chatSend(conn)       //開始用戶端輪訓       buf := make([]byte, 1024)       for {           lenght, err := conn.Read(buf)           if checkError(err, "Connection") == false {               conn.Close()               fmt.Println("Server is dead ...ByeBye")               os.Exit(0)           }           fmt.Println(string(buf[0:lenght]))       }   }   ////////////////////////////////////////////////////////   //   //主程式   //   //參數說明:   //  啟動伺服器端:  Chat server [port]             eg: Chat server 9090   //  啟動用戶端:    Chat client [Server Ip Addr]:[Server Port]    eg: Chat client 192.168.0.74:9090   //   ////////////////////////////////////////////////////////   func main() {       if len(os.Args) != 3 {           fmt.Println("Wrong pare")           os.Exit(0)       }       if os.Args[1] == "server" && len(os.Args) == 3 {           StartServer(os.Args[2])       }       if os.Args[1] == "client" && len(os.Args) == 3 {           StartClient(os.Args[2])       }   }
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.