diff --git a/src/github.com/cmu440/p0/server_impl.go b/src/github.com/cmu440/p0/server_impl.go index 52792e1..0480901 100644 --- a/src/github.com/cmu440/p0/server_impl.go +++ b/src/github.com/cmu440/p0/server_impl.go @@ -9,11 +9,14 @@ import ( ) type multiEchoServer struct { - clients map[string] net.Conn - clientMsgs map[string] chan([] byte) - listener net.Listener - read chan []byte - stop bool + clients map[string] net.Conn + clientMsgs map[string] chan([] byte) + listener net.Listener + readChan chan []byte + closeCliChan chan string + addCliChan chan net.Conn + countRequestChan chan chan int + closeChan chan bool } // New creates and returns (but does not start) a new MultiEchoServer. @@ -21,35 +24,35 @@ func New() MultiEchoServer { mes := &multiEchoServer{ clients: make(map[string] net.Conn), clientMsgs: make(map[string] chan([]byte)), - read: make(chan([]byte)), - stop: false, + readChan: make(chan([]byte)), + closeCliChan: make(chan string), + addCliChan: make(chan net.Conn), + countRequestChan: make(chan chan int), + closeChan: make(chan bool), } return MultiEchoServer(mes); } func (mes *multiEchoServer) Start(port int) error { - mes.stop = false; listener, e := net.Listen("tcp", fmt.Sprintf(":%d", port)); if e != nil { fmt.Println("listen tcp failed"); return e; } mes.listener = listener; - go mes.handleListen(); - go mes.handleDistributeMsg(); + go mes.handleEvent(); + go mes.handleAccept(); return nil; } func (mes *multiEchoServer) Close() { - mes.stop = true; - mes.listener.Close(); - for _, conn := range mes.clients{ - conn.Close(); - } + mes.closeChan <- true; } func (mes *multiEchoServer) Count() int { - return len(mes.clients); + countChan := make(chan int); + mes.countRequestChan<-countChan; + return <-countChan; } // TODO: add additional methods/functions below! @@ -59,12 +62,10 @@ func (mes *multiEchoServer) handleConn(conn net.Conn) { for { line, e := reader.ReadBytes('\n'); if e != nil{ - fmt.Println("read close connetion, client : " + conn.RemoteAddr().String()); - delete(mes.clients, conn.RemoteAddr().String()); - conn.Close(); + mes.closeCliChan <-conn.RemoteAddr().String(); return; } - mes.read <- line; + mes.readChan <- line; } } @@ -74,37 +75,53 @@ func (mes *multiEchoServer) handleWrite(conn net.Conn) { msg := <- msgChan; _, e := conn.Write(msg); if e != nil { - delete(mes.clients, conn.RemoteAddr().String()); + mes.closeCliChan <-conn.RemoteAddr().String(); + return; } } } -func (mes *multiEchoServer) handleListen() { +func (mes *multiEchoServer) handleAccept() { for { conn, e := mes.listener.Accept(); if e != nil { - if mes.stop == true { - fmt.Println("listen stop") - return - } - continue; - } - if _, ok := mes.clientMsgs[conn.RemoteAddr().String()]; !ok { - mes.clientMsgs[conn.RemoteAddr().String()] = make(chan []byte, 100); + fmt.Println("listen stop") + return } - mes.clients[conn.RemoteAddr().String()] = conn; - go mes.handleConn(conn); + mes.addCliChan<-conn; } } -func (mes *multiEchoServer) handleDistributeMsg() { +func (mes *multiEchoServer) handleEvent() { for { - line := <- mes.read; - for key, _ := range mes.clients { - msgChan := mes.clientMsgs[key]; - if len(msgChan) < 100 { - msgChan <- line; + select { + case line := <-mes.readChan: + for key, _ := range mes.clients { + msgChan := mes.clientMsgs[key]; + if len(msgChan) < 100 { + msgChan <- line; + } } + case addr := <-mes.closeCliChan: + if conn, ok := mes.clients[addr]; ok { + conn.Close(); + delete(mes.clients, addr); + } + case countChan := <-mes.countRequestChan: + cnt := len(mes.clients); + countChan<-cnt; + case conn := <-mes.addCliChan: + if _, ok := mes.clientMsgs[conn.RemoteAddr().String()]; !ok { + mes.clientMsgs[conn.RemoteAddr().String()] = make(chan []byte, 100); + } + mes.clients[conn.RemoteAddr().String()] = conn; + go mes.handleConn(conn); + case <-mes.closeChan: + mes.listener.Close(); + for _, conn := range mes.clients { + conn.Close(); + } + return; } } } \ No newline at end of file