寫在前面
Go語言在很多方面天然的具備很多便捷性,譬如網路編程,并發編程,而通道則又是Go語言實作并發編程的重要工具,因為其承擔著通道之間互相通信的重任,并且因為其本身就是并發安全的,所以在某些場景下是非常好用的,
并發聊天服務器
這里主要是實作一個簡單的并發聊天服務器,首先,客戶端可以在服務器中注冊自己的資訊(登錄以及退出),客戶端發出的所有的資訊由服務器向各個客戶端進行轉發,或者換句話說是廣播,
具體代碼
服務端
說的再多,沒有代碼簡單明了,直接上代碼~
package main
import (
"bufio"
"fmt"
"log"
"net"
)
type client chan <- string //定義一個單向的向外發送資料的通道
var (
entering = make(chan client)
leaving = make(chan client)
messages = make(chan string)
)
func main() {
listener, err := net.Listen("tcp","localhost:8000")
if err != nil {
log.Fatal("network is broken", err)
}
go broadcaster()
for {
conn, err := listener.Accept()
if err != nil {
log.Print(err)
continue
}
go handleConn1(conn)
}
}
func broadcaster() {
clients := make(map[client]bool) //存盤每個client的登錄狀態
for{
select {
case msg := <-messages:
for cli := range clients {
cli <- msg
}
case cli := <-entering:
clients[cli] = true
case cli := <-leaving:
delete(clients,cli)
close(cli)
}
}
}
func handleConn1(conn net.Conn) {
ch := make(chan string)
go clientWriter(conn, ch)
who := conn.RemoteAddr().String()
ch <- "You are " + who
entering <- ch
messages <- who + "has arrived"
input := bufio.NewScanner(conn)
for input.Scan() {
messages <- who + ":" + input.Text()
}
leaving <- ch
messages <- who + "has left"
conn.Close()
}
func clientWriter(conn net.Conn, ch <- chan string) {
for msg := range ch {
fmt.Fprintln(conn, msg)
}
}
客戶端
客戶端相對簡單,只是涉及到資訊的發送和接受作業,
package main
import (
"io"
"log"
"net"
"os"
)
func main() {
conn, err := net.Dial("tcp","localhost:8000")
if err != nil {
log.Fatal("Connected has been refused!",err)
}
defer conn.Close()
go mesCopy(os.Stdout,conn)
mesCopy(conn,os.Stdin)
}
func mesCopy(des io.Writer, res io.Reader) {
if _, err := io.Copy(des, res); err != nil {
log.Print("wrong!")
}
}
總結
實作原理較為簡單,所以代碼并沒有多少注釋,如果有任何疑問,歡迎留言討論,最后說一句,在MIT的課程中,其實并不是很推薦在并發編程中使用通道chan,除非你對其應用的場景和可能出現的情況有很好的把握,不然可能會出現很多不可預測的事情,譬如死鎖(見另外一篇博客),在這種時候,共享變數將會是一種很好的選擇,具體查看go多執行緒實踐,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/280542.html
標籤:區塊鏈
上一篇:指數基金投資指南——閱讀筆記
