golang에서 데모 TCP 채팅 서버를 구현했지만 정상적으로 작동하지만 사용자가 연결을 끊을 때마다 브로드 캐스트 채널에 메시지를 작성하여 다른 사용자가 사용자가 블록을 연결 해제했으며 버퍼가없는 채널이기 때문에 다른 클라이언트의 새 메시지를 더 이상 처리하지 않습니다.Go : go 채널의 교착 상태 문제 및 선택
코드로 댓글을 달았으며 설명 할 수있는 이유를 설명했습니다. 블록, 내가 작성한 MSG를
나는 토륨을 작성한 채널- E 채널은
- I는 채널
에서 읽은 메시지는 여전히 완벽하게하기 위해 내 MSG 채널 블록에 있습니다.
Ps : 버퍼링 된 채널을 사용하는 경우 코드가 차단되지 않지만 내 코드가 어디서 멈추는 지 알고 싶습니다. 가 나는 또한 내 -race 플래그 코드 만 이동에서
package main
import (
"fmt"
"io"
"net"
"sync"
)
func main() {
msg := make(chan string) //broadcast channel (making it buffered channel the problem goes away)
allConn := make(map[net.Conn]int) //Collection of incoming connections for broadcasting the message
disConn := make(chan net.Conn) //client disconnect channel
newConn := make(chan net.Conn) //new client connection channel
mutext := new(sync.RWMutex) //mux to assign unique id to incoming connections
i := 0
listener, err := net.Listen("tcp", "127.0.0.1:8081")
checkErr(err)
fmt.Println("Tcp server started at 127.0.0.1:8081")
//Accept incoming connections and store them in global connection store allConn
go func() {
for {
conn, err := listener.Accept()
checkErr(err)
mutext.Lock()
allConn[conn] = i
i++
mutext.Unlock()
newConn <- conn
}
}()
for {
select {
//Wait for a new client message to arrive and broadcast the message
case umsg := <-msg:
fmt.Println("Broadcast Channel: Already Read")
bmsg := []byte(umsg)
for conn1, _ := range allConn {
_, err := conn1.Write(bmsg)
checkErr(err)
}
//Handle client disconnection [disConn]
case conn := <-disConn:
mutext.RLock()
fmt.Println("user disconneting", allConn[conn])
mutext.RUnlock()
delete(allConn, conn)
fmt.Println("Disconnect: About to Write")
//this call results in deadlock even when channel is empty, buffered channel resolves the issue
//need to know why
msg <- fmt.Sprintf("Disconneting", allConn[conn])
fmt.Println("Disconnect: Already Written")
//Read client incoming message and put it on broadcasting channel and upon disconnect put on it disConn channel
case conn := <-newConn:
go func(conn net.Conn) {
for {
buf := make([]byte, 64)
n, err := conn.Read(buf)
if err != nil {
if err == io.EOF {
disConn <- conn
break
}
}
fmt.Println("Client: About to Write")
msg <- string(buf[0:n])
fmt.Println("Client: Already Written")
}
}(conn)
mutext.RLock()
fmt.Println("User Connected", allConn[conn])
mutext.RUnlock()
}
}
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}
자세한 내용은 https://golang.org/ref/mem#tmp_7 (앵커가 변경되면 "채널 통신"섹션)에 설명되어 있습니다. – Vatine