Golang實現簡單tcp服務器03 -- 文本廣播式聊天服務器/客戶端

用Golang實現 文本廣播式聊天服務器/客戶端

本節, 咱們將一步一步的把上一節完成的echo服務器/客戶端改形成一個文本信息的聊天室git

服務端的改動服務器

  1. 服務器爲了實現聊天信息的羣體廣播, 須要記錄全部鏈接到服務器的客戶端信息, 因此, 咱們須要添加一個集合來保存全部客戶端的鏈接:併發

    var ConnMap map[string]*net.TCPConntcp

  2. 接着, 每次當有新的客戶端鏈接到服務器時, 須要把這個客戶端鏈接行信息加入集合:ui

    ConnMap[tcpConn.RemoteAddr().String()] = tcpConn.net

  3. 當服務器收到客戶端的聊天信息時, 須要廣播到全部客戶端, 因此咱們須要利用上面保存TCPConn的map來遍歷全部TCPConn進行廣播, 用如下方法實現:code

    func boradcastMessage(message string) {
     	b := []byte(message)
     	for _, conn := range ConnMap {
     	conn.Write(b)
     	}
     }

客戶端代碼改動server

客戶端代碼改動相對簡單, 只是加入了用戶本身輸入聊天信息的功能, 在鏈接成功而且 啓動了消息接收的gorountine後, 加入如下代碼:ip

for {
		var msg string
		fmt.Scanln(&msg)
		if msg == "quit" {
			break
		}
		b := []byte(msg + "\n")
		conn.Write(b)
	}

完整的服務端代碼以下:ci

server.go

package main

import (
	"bufio"
	"fmt"
	"net"
)

// 用來記錄全部的客戶端鏈接
var ConnMap map[string]*net.TCPConn

func main() {
	var tcpAddr *net.TCPAddr
	ConnMap = make(map[string]*net.TCPConn)
	tcpAddr, _ = net.ResolveTCPAddr("tcp", "127.0.0.1:9999")

	tcpListener, _ := net.ListenTCP("tcp", tcpAddr)

	defer tcpListener.Close()

	for {
		tcpConn, err := tcpListener.AcceptTCP()
		if err != nil {
			continue
		}

		fmt.Println("A client connected : " + tcpConn.RemoteAddr().String())
		// 新鏈接加入map
		ConnMap[tcpConn.RemoteAddr().String()] = tcpConn
		go tcpPipe(tcpConn)
	}

}

func tcpPipe(conn *net.TCPConn) {
	ipStr := conn.RemoteAddr().String()
	defer func() {
		fmt.Println("disconnected :" + ipStr)
		conn.Close()
	}()
	reader := bufio.NewReader(conn)

	for {
		message, err := reader.ReadString('\n')
		if err != nil {
			return
		}
		fmt.Println(conn.RemoteAddr().String() + ":" + string(message))
		// 這裏返回消息改成了廣播
		boradcastMessage(conn.RemoteAddr().String() + ":" + string(message))
	}
}


func boradcastMessage(message string) {
	b := []byte(message)
	// 遍歷全部客戶端併發送消息
	for _, conn := range ConnMap {
		conn.Write(b)
	}
}

客戶端完整代碼以下:

client.go

package main

import (
	"bufio"
	"fmt"
	"net"
)

func main() {
	var tcpAddr *net.TCPAddr
	tcpAddr, _ = net.ResolveTCPAddr("tcp", "127.0.0.1:9999")

	conn, _ := net.DialTCP("tcp", nil, tcpAddr)
	defer conn.Close()
	fmt.Println("connected!")

	go onMessageRecived(conn)
	
	// 控制檯聊天功能加入
	for {
		var msg string
		fmt.Scanln(&msg)
		if msg == "quit" {
			break
		}
		b := []byte(msg + "\n")
		conn.Write(b)
	}
}

func onMessageRecived(conn *net.TCPConn) {
	reader := bufio.NewReader(conn)
	for {
		msg, err := reader.ReadString('\n')
		fmt.Println(msg)
		if err != nil {
			quitSemaphore <- true
			break
		}
	}
}

最後分別編譯server與client試試效果吧!

go build server.go

go build client.go

先啓動server端, 而後新開兩個個終端, 啓動客戶端, 在其中一個客戶端裏鍵入聊天信息後回車, 會發現另一個客戶端收到了剛剛發送的聊下天信息

完事大吉!

相關源碼: https://git.oschina.net/victoriest/go-simple-tcp-server.git

相關文章
相關標籤/搜索