#### 简单实现了一个echo服务器
#### 对于每个链接,封装了一个TcpConn处理,并且开了4个goroutine处理分别处理读、写、逻辑、关闭(据说goroutine开销很小,一对4的关系有问题么)
#### 现在的问题是逻辑代码中,因为一些操作延迟,导致sendChan被关闭,所以不得不再加了关闭锁的判断,有什么办法优化么
```go
package main
import (
"log"
"net"
"sync"
"time"
)
type TcpConn struct {
conn net.Conn
dataChan chan []byte
sendChan chan []byte
closeChan chan bool
closeFlag bool
closeLock sync.Mutex
}
func (self *TcpConn) send() {
for buff := range self.sendChan {
_, err := self.conn.Write(buff)
if err != nil {
log.Println("send error", err)
break
}
}
self.close()
}
func (self *TcpConn) recv() {
tmp := make([]byte, 1024)
for {
len, err := self.conn.Read(tmp)
if err != nil {
log.Println("recv error", err)
break
}
data := make([]byte, len)
copy(data, tmp[:len])
self.dataChan <- data
}
self.close()
}
func (self *TcpConn) doLogic() {
for b := range self.dataChan {
time.Sleep(1500 * time.Millisecond)
//加了这个关闭判断,不然会报错 send on closed channel
//if self.closeFlag {
// return
//}
//self.closeLock.Lock()
//if self.closeFlag {
// return
//}
//self.closeLock.Unlock()
self.sendChan <- b
}
}
func (self *TcpConn) close() {
if self.closeFlag {
return
}
self.closeLock.Lock()
defer self.closeLock.Unlock()
if self.closeFlag {
return
}
self.closeFlag = true
self.closeChan <- true
}
func main() {
listener, err := net.Listen("tcp", "0.0.0.0:7788")
if err != nil {
log.Fatal("run err", err)
}
log.Println("server run at 7788")
defer listener.Close()
for {
conn, err := listener.Accept()
if err != nil {
log.Fatal("accept err", err)
}
log.Println("one connect come")
client := &TcpConn{
conn: conn,
dataChan: make(chan []byte),
sendChan: make(chan []byte),
closeChan: make(chan bool),
closeFlag: false,
closeLock: sync.Mutex{},
}
go func() {
go client.send()
go client.recv()
go client.doLogic()
select {
case <-client.closeChan:
log.Println("close net.Conn")
conn.Close()
}
close(client.closeChan)
close(client.dataChan)
close(client.sendChan)
log.Println("one tcp end")
}()
}
}
```
1.我觉得不需要优化。用锁的确有一定代价,但是socket操作设计io操作,消耗要大几个数量级。考虑这个意义不大
2.你这个只是关闭标志的话可以不用锁,用原子操作就可以了,看看atomic包吧.
#1