|
学习golang的时间断断续续加起来也有将近一个月了,这期间都是偶看翻几页书,没有写过实际的代码.最近做一个app项目,是一个展示类 的软件,当客户要看某个图片时首先向服务器发出一个请求,比对图片的版本,如果版本与本地一致,则直接显示,如果版本落后了则由服务 器将最新的版本发送给客户端.
对服务器的需求就是一个简单的版本比对和文件传输,于是打算用go去实现,正好也可以练练手.
在设计上,受到以往框架设计的影响,还是使用了wpacket,rpacket和共享buffer这个方案,不同的地方是go的网络API不支持 gather io,所以buffer没有被实现为buffer list,而是一整块的连续内存,当buffer空间不足时需要手动的去扩展内存.
下面说点与以往用C设计网络框架不同的地方,对于已经习惯了使用异步回调方式来使用网络的我,刚开始用go来做一个网络框架还是稍有不适. go的网络API都是同步的,也不存在select,epoll,poll这类东西,这也就意味着需要使用goroutine来实现并发.
我的做法是这样的,首先定义了一个类型Tcpconnection
type Tcpsession struct{
Conn net.Conn
Packet_que chan interface{}
Send_que chan
*packet.Wpacket
raw bool
send_close bool
}
其中Conn成员是连接对象,Packet_que是一个管道,用于接收收到的网络包和连接事件.Send_que是另一个管道,用来将需要发送 的数据包传给sender。
func NewTcpSession(conn net.Conn,raw bool)(*Tcpsession){
session :
= &Tcpsession{Conn:conn,Packet_que:make(chan interface{},1024),Send_que:make(chan *packet.Wpacket,1024),raw:raw,send_close:false}
if raw{
go dorecv_raw(session)
}
else{
go dorecv(session)
}
go dosend(session)
return session
}
在建立一个新连接之后,启动两个goroutine分别用于执行recv和send.
func dorecv_raw(session *Tcpsession){
for{
recvbuf :
= make([]byte,packet.Max_bufsize)
_,err :
= session.Conn.Read(recvbuf)
if err != nil {
session.Packet_que |
|