Sivo 悉见

请用golang写一个简单的聊天室,包含服务端客户端

匿名 · 更新于 2023/3/20

以下是一个简单的 Golang 聊天室示例,包括服务端和客户端:

服务端代码:

package main

import ( "fmt" "net" )

type client chan<- string // 只能发送 string 类型的消息的通道类型别名

var ( entering = make(chan client) leaving = make(chan client) messages = make(chan string) // 所有客户端共享的消息通道 )

func broadcaster() { clients := make(map[client]bool) // 客户端集合 for { select { case msg := <-messages: // 把收到的消息发送给所有客户端 for cli := range clients { cli <- msg } case cli := <-entering: // 新客户端连接 clients[cli] = true cli <- "Welcome to the chat room!" case cli := <-leaving: // 客户端离开 delete(clients, cli) close(cli) } } }

func handleConn(conn net.Conn) { ch := make(chan string) // 发送给客户端的消息通道 go clientWriter(conn, ch)

who := conn.RemoteAddr().String()
ch &lt;- &quot;You are &quot; + who
messages &lt;- who + &quot; has arrived&quot;
entering &lt;- ch

input := make(chan string) // 接收客户端的消息通道
go clientReader(conn, input)

for {
	select {
	case line, ok := &lt;-input:
		if !ok {
			break
		}
		messages &lt;- who + &quot;: &quot; + line
	}
}

leaving &lt;- ch
messages &lt;- who + &quot; has left&quot;
conn.Close()

}

func clientWriter(conn net.Conn, ch <-chan string) { for msg := range ch { fmt.Fprintln(conn, msg) } }

func clientReader(conn net.Conn, ch chan<- string) { buf := make([]byte, 1024) for { n, err := conn.Read(buf) if err != nil { break } ch <- string(buf[:n]) } close(ch) }

func main() { listener, err := net.Listen("tcp", ":8888") if err != nil { panic(err) }

go broadcaster()

for {
	conn, err := listener.Accept()
	if err != nil {
		fmt.Printf(&quot;failed to accept connection: %s\n&quot;, err)
		continue
	}
	go handleConn(conn)
}

}

 

客户端代码:


package main

import ( "bufio" "fmt" "net" "os" "strings" )

func main() { conn, err := net.Dial("tcp", "localhost:8888") if err != nil { panic(err) } defer conn.Close()

go func() {
	// 接收服务端的消息并输出到控制台
	scanner := bufio.NewScanner(conn)
	for scanner.Scan() {
		fmt.Println(scanner.Text())
	}
}()

// 从控制台读取输入并发送到服务端
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
	line := scanner.Text()
	if strings.TrimSpace(line) == &quot;&quot; {
		continue
	}
	fmt.Fprintf(conn, &quot;%s\n&quot;, line)
}

}

 

运行服务端代码后,可以同时运行多个客户端连接到聊天服务器