我有一个 UDP 服务器,它公开两个端口,8080 用于正常数据,8082 用于控制(保持活动信号)。当我启动服务器时,会创建一个新的 Server 实例。它有一个客户端列表:一个由 struct that
表示的客户端包含两种类型的 UDPConn
,一种用于控制,一种用于数据。发生的情况是,当我运行 Client.go
时,我在两个端口都连接到服务器,但是服务器创建了两个客户端而不是一个客户端。向下是我的 Server.go
和 Client.go
的一部分。如何为两个连接只创建一个用户?
Server.go
func main() {
server := NewLobby()
addressCntrl, err := net.ResolveUDPAddr(CONN_TYPE, CONN_CNTRL_PORT)
if err != nil {
log.Fatalf("Error resolving controller address: %s", err)
}
listenerCntrl, err := net.ListenUDP(CONN_TYPE, addressCntrl)
defer listenerCntrl.Close()
log.Printf("Listening controll on port %s", CONN_CNTRL_PORT)
addressData, err := net.ResolveUDPAddr(CONN_TYPE, CONN_DATA_PORT)
if err != nil {
log.Fatalf("Error Resolving data address: %s", err)
}
listenerData, err := net.ListenUDP(CONN_TYPE, addressData)
defer listenerData.Close()
log.Printf("Listening data on port %s", CONN_DATA_PORT)
for {
buffer = make([]byte, 1024)
listenerData.ReadFromUDP(buffer)
c := NewClient(*listenerData, *listenerCntrl)
server.Join(c)
}
}
新服务器 (server.go)
func NewServer() *Server {
server := &Server{
clients: make([]*Client, 0),
chatRooms: make(map[string]*ChatRoom),
incoming: make(chan *Message),
join: make(chan *Client),
leave: make(chan *Client),
delete: make(chan *ChatRoom),
}
server.Listen()
return server
}
NewClient (server.go)
func NewClient(connData net.UDPConn, connCntrl net.UDPConn) *Client {
writerData := bufio.NewWriter(&connData)
readerData := bufio.NewReader(&connData)
writerCntrl := bufio.NewWriter(&connCntrl)
readerCntrl := bufio.NewReader(&connCntrl)
client := &Client{
name: CLIENT_NAME,
chatRoom: nil,
incoming: make(chan *Message),
outgoing: make(chan string),
connData: connData,
connCntrl: connCntrl,
readerData: readerData,
writerData: writerData,
readerCntrl: readerCntrl,
writerCntrl: writerCntrl,
}
log.Printf("New client connected")
client.Listen()
return client
}
Client.go
func main() {
server := NewServer()
addressCntrl, err := net.ResolveUDPAddr(CONN_TYPE, CONN_CNTRL_PORT)
if err != nil {
log.Fatalf("Error resolving controller address: %s", err)
}
listenerCntrl, err := net.ListenUDP(CONN_TYPE, addressCntrl)
defer listenerCntrl.Close()
log.Printf("Listening controll on port %s", CONN_CNTRL_PORT)
addressData, err := net.ResolveUDPAddr(CONN_TYPE, CONN_DATA_PORT)
if err != nil {
log.Fatalf("Error Resolving data address: %s", err)
}
listenerData, err := net.ListenUDP(CONN_TYPE, addressData)
defer listenerData.Close()
log.Printf("Listening data on port %s", CONN_DATA_PORT)
for {
buffer = make([]byte, 1024)
listenerData.ReadFromUDP(buffer)
c := NewClient(*listenerData, *listenerCntrl)
server.Join(c)
}
}
输出示例如下
服务器输出
2021/05/06 20:03:52 Listening controll on port :8082
2021/05/06 20:03:52 Listening data on port :8080
2021/05/06 20:03:56 New client connected
2021/05/06 20:03:58 New client connected
客户端输出
Welcome to the server! Type "/help" to get a list of commands.
Welcome to the server! Type "/help" to get a list of commands.
如果需要,我的函数 Read()
和 Write()
客户端如下。
阅读(client.go)
func Read(connData net.UDPConn, connCntrl net.UDPConn) {
//Controller
go func() {
readerCntrl := bufio.NewReader(&connCntrl)
for {
str, _ := readerCntrl.ReadString('\n')
if strings.Compare(str, "timeout") == 0 {
os.Exit(1)
}
}
}()
//Data
reader := bufio.NewReader(&connData)
for {
str, err := reader.ReadString('\n')
if err != nil {
fmt.Printf(MSG_DISCONNECT)
wg.Done()
return
}
fmt.Print(str)
}
}
写入(client.go)
func Write(connData net.UDPConn, connCntrl net.UDPConn) {
//Controller
go func() {
writerCntrl := bufio.NewWriter(&connCntrl)
for range time.Tick(10 * time.Second) {
writerCntrl.WriteString("ka")
}
}()
//Data
reader := bufio.NewReader(os.Stdin)
writerData := bufio.NewWriter(&connData)
for {
input, err := reader.ReadString('\n')
if err != nil {
log.Fatalf("Error reading input: %s", err)
}
_, err = writerData.WriteString(input)
if err != nil {
log.Fatalf("Error writing input to server: %s", err)
}
err = writerData.Flush()
if err != nil {
log.Fatalf("Error flushing the input: %s", err)
wg.Done()
}
}
}