Skip to content

Commit

Permalink
race condition
Browse files Browse the repository at this point in the history
  • Loading branch information
Yu guangyuan committed Aug 25, 2016
1 parent e40250f commit 81dcd48
Showing 1 changed file with 55 additions and 38 deletions.
93 changes: 55 additions & 38 deletions src/github.com/cmu440/p0/server_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,47 +9,50 @@ 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.
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!
Expand All @@ -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;
}
}

Expand All @@ -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;
}
}
}

0 comments on commit 81dcd48

Please sign in to comment.