背景
我正在使用Golang创建聊天室服务器。每次客户端连接到服务器时,我都将Client函数作为新线程启动,以便每个客户端都获得一个被监听的线程。我能够基于this tutorial创建一个简单的客户端服务器连接,但是现在我正在尝试为多个客户端创建连接,以便它们可以将消息发送到聊天室。
代码说明
在this tutorial之后,看来我可以使用go func()
创建线程,并等待包含通道(<-newClient
)的建立。在调用用户函数之前,我将bool值传递给通道,因为用户函数将永远运行,并且我想建立其他客户端连接。每个客户端连接都会为其运行用户功能。
问题
我不知道如何将用户连接变量传递给其他函数。我将conn net
放在函数的参数中,但这只是一个占位符,因为我不确定这样做的正确方法。
此外,我的go func()
在实现通道之后调用user()是我在多线程上的最佳尝试,但是我不确定我是否正在考虑正确。
Server.go
package main
import (
"net"
"fmt"
"bufio"
"strings"
"container/list"
"time"
)
type chatRoom struct {
name string
messages list.List
users list.List
lastUsed time.Time
}
var chatRooms *list.List //A list of chatrooms where each client can post messages, where messages can be seen by all clients in the chatroom
var conn net.Conn
func user(conn net) {
for {
message, _ := bufio.NewReader(conn).ReadString('\n') // will listen for message to process ending in newline (\n)
fmt.Print("Message Received:", string(message)) // output message received
s := strings.Split(string(message), ":")
if strings.Compare(s[0],"create") == 0{ //create a chat room
create(conn, s[1])
}else if strings.Compare(s[0],"list") == 0 { //List the current chatrooms
msg = listRooms(conn)
}else if strings.Compare(s[0],"join") == 0 { //Join the user to a chat room
join(conn, s[1])
}else if strings.Compare(s[0],"leave") == 0 { //Remove the user from a chatroom
leave(conn, s[1])
}else if strings.Compare(s[0],"message") == 0{ //Send a message to a chatroom
message(conn, s[1], s[2])
}
}
}
func main() {
fmt.Println("Launching server...")
this.userList = list.New()
this.chatRooms = list.New();
ln, _ := net.Listen("tcp", ":8081") // listen on all interfaces
conn, _ := ln.Accept() // accept connection on port
for { // run loop forever (or until ctrl-c)
go func(){
newClient := make(chan bool)
ln, _ := net.Listen("tcp", ":8081") // listen on all interfaces
conn, _ := ln.Accept() // accept connection on port
newClient <- true
user(conn)
}
<-newClient
}
}
答案 0 :(得分:1)
在这里理解区别非常重要:这是并发性,而不是多线程,而这些是 goroutines ,而不是线程。这些概念是不可互换的。关于您的核心问题,您的实施存在一些重大问题:
conn
。每次接受连接时,您将覆盖每个goroutine共享的conn
。您应该将conn
传递到您的goroutine,使其具有自己的本地副本,或者在每次循环迭代中创建一个新的conn
变量,而不是重复使用。 / li>
ln.Accept
即可继续接受新连接。查看net
package的文档介绍,或查看在Go中使用侦听器的任何代码。newClient
,然后尝试在goroutine之外引用它。甚至不会编译,而且不清楚您最初打算如何使用此通道。在net
或net/http
库中或GitHub上的一些流行项目中,查看一些现有的网络代码,以查看有关如何编写网络应用程序的良好示例。对博客文章或教程或操作方法进行一些网络搜索,结果很多。并且一定要阅读所用软件包的文档,这对您有很大帮助。