在上面的4篇文章中,我们已经搭建了一个简易的socket通讯框架,但是有一个问题。如果服务端主动关闭了连接,这时候client端就接收不到服务端发送的消息。这时候我们就需要做一个断线重连的处理。
在这里,我们采用判断共享内存的方式,既当接收不到服务器端发送的消息时,向channel中写入数据。
//接收服务端发来的消息
func ReadMsg(conn net.Conn,ch chan int) {
//存储被截断的数据
tmpbuf:=make([] byte,0)
buf:=make([] byte,1024)
//将信息解包
n,_:=conn.Read(buf)
tmpbuf = protocol.Depack(append(tmpbuf,buf[:n]...))
msg:=string(tmpbuf)
fmt.Println("server say:",msg)
if len(msg)==0{
//服务端无返回信息
ch<-2
}
}
而在主函数中,我们使用一个for循环,来进行断线重连,即doWork。
func main() {
if len(os.Args) !=2 {
fmt.Fprintf(os.Stderr,"Usage:%s IP:Port\n",os.Args[0])
os.Exit(1)
}
//动态传入服务端IP和端口号
service:=os.Args[1]
tcpAddr,err:=net.ResolveTCPAddr("tcp4",service)
CheckError(err)
for{
conn,err:=net.DialTCP("tcp",nil,tcpAddr)
if err!=nil{
fmt.Fprintf(os.Stderr,"Fatal error:%s",err.Error())
}else{
defer conn.Close()
doWork(conn)
}
time.Sleep(3 * time.Second)
}
}
doWork的具体方法实现为:
//解决断线重连问题
func doWork(conn net.Conn) error {
ch:=make(chan int,100)
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for{
select {
case stat:=<-ch:
if stat==2{
return errors.New("None Msg")
}
case <-ticker.C:
ch<-1
go ClientMsgHandler(conn,ch)
case <-time.After(time.Second*10):
defer conn.Close()
fmt.Println("timeout")
}
}
return nil
}