tcp长连接处理服务端和客户端处理方式

长连接的处理方式是:

Server端收到Client端发来的信息之后,开始心跳计时,在设定时间内如果收到Client发来的消息,则重置计时器,否则计时结束断开连接。

Client端,处理方式是:用time.NewTicker创建一个定时器,每间隔一秒发送下当前时间到服务器。

服务端代码如下:

  1. package main  
  2.   
  3. import (  
  4.     "fmt"  
  5.     "os"  
  6.     "net"  
  7.     "log"  
  8.     "github.com/mxi4oyu/MoonSocket/protocol"  
  9.     "time"  
  10. )  
  11.   
  12.   
  13. //定义CheckError方法,避免写太多到 if err!=nil  
  14. func CheckError(err error)  {  
  15.   
  16.     if err!=nil{  
  17.         fmt.Fprintf(os.Stderr,"Fatal error:%s",err.Error())  
  18.   
  19.         os.Exit(1)  
  20.     }  
  21.   
  22. }  
  23.   
  24. //自定义log  
  25. func Log(v... interface{})  {  
  26.   
  27.     log.Println(v...)  
  28. }  
  29.   
  30. func main()  {  
  31.   
  32.     server_listener,err:=net.Listen("tcp","localhost:8848")  
  33.   
  34.     CheckError(err)  
  35.   
  36.     defer server_listener.Close()  
  37.   
  38.     Log("Waiting for clients connect")  
  39.   
  40.   
  41.   
  42.     for{  
  43.         new_conn,err:=server_listener.Accept()  
  44.   
  45.         CheckError(err)  
  46.   
  47.         go ServerMsgHandler(new_conn)  
  48.     }  
  49.   
  50.       
  51. }  
  52.   
  53. //服务端消息处理  
  54. func ServerMsgHandler(conn net.Conn)  {  
  55.   
  56.     //存储被截断的数据  
  57.     tmpbuf:=make([] byte,0)  
  58.     buf:=make([] byte,1024)  
  59.   
  60.     defer conn.Close()  
  61.   
  62.     //接收解包  
  63.     readchan:=make(chan [] byte,16)  
  64.     go ReadChan(readchan)  
  65.   
  66.     for{  
  67.         n,err:=conn.Read(buf)  
  68.   
  69.         if err!=nil{  
  70.   
  71.             fmt.Println("connection close")  
  72.             return  
  73.         }  
  74.   
  75.         //解包  
  76.         tmpbuf = protocol.Depack(append(tmpbuf,buf[:n]...))  
  77.         fmt.Println("client say:",string(tmpbuf))  
  78.   
  79.         Msg:=tmpbuf  
  80.   
  81.         beatch :=make(chan byte)  
  82.         //心跳计时,默认30秒  
  83.         go HeartBeat(conn,beatch,30)  
  84.         //检测每次Client是否有数据传来  
  85.         go HeartChanHandler(Msg,beatch)  
  86.   
  87.     }  
  88.   
  89. }  
  90.   
  91. //处理心跳,根据HeartChanHandler判断Client是否在设定时间内发来信息  
  92. func HeartBeat(conn net.Conn,heartChan chan byte,timeout int)  {  
  93.     select {  
  94.     case hc:=<-heartChan:  
  95.         Log("<-heartChan:",string(hc))  
  96.         conn.SetDeadline(time.Now().Add(time.Duration(timeout)*time.Second))  
  97.         break  
  98.     case <-time.After(time.Second*30):  
  99.         Log("timeout")  
  100.         conn.Close()  
  101.     }  
  102. }  
  103.   
  104. //处理心跳channel  
  105. func HeartChanHandler( n [] byte,beatch chan byte)  {  
  106.     for _,v:=range n{  
  107.         beatch<-v  
  108.     }  
  109.     close(beatch)  
  110. }  
  111.   
  112. //从channell中读取数据  
  113. func ReadChan(readchan chan [] byte)  {  
  114.   
  115.     for{  
  116.         select {  
  117.         case data:=<-readchan:  
  118.             Log(string(data))  
  119.         }  
  120.     }  
  121. }  

客户端代码如下:

  1. package main  
  2.   
  3. import (  
  4.     "fmt"  
  5.     "os"  
  6.     "net"  
  7.     "strconv"  
  8.     "time"  
  9.     "github.com/mxi4oyu/MoonSocket/protocol"  
  10. )  
  11.   
  12. //定义CheckError方法,避免写太多到 if err!=nil  
  13. func CheckError(err error)  {  
  14.   
  15.     if err!=nil{  
  16.         fmt.Fprintf(os.Stderr,"Fatal error:%s",err.Error())  
  17.   
  18.         os.Exit(1)  
  19.     }  
  20.   
  21. }  
  22.   
  23. func main()  {  
  24.   
  25.     if len(os.Args) !=2 {  
  26.   
  27.         fmt.Fprintf(os.Stderr,"Usage:%s IP:Port\n",os.Args[0])  
  28.   
  29.         os.Exit(1)  
  30.     }  
  31.   
  32.     //动态传入服务端IP和端口号  
  33.     service:=os.Args[1]  
  34.   
  35.     tcpAddr,err:=net.ResolveTCPAddr("tcp4",service)  
  36.   
  37.     CheckError(err)  
  38.   
  39.     conn,err:=net.DialTCP("tcp",nil,tcpAddr)  
  40.   
  41.     CheckError(err)  
  42.     ch:=make(chan int,100)  
  43.   
  44.     ticker := time.NewTicker(time.Second)  
  45.     defer ticker.Stop()  
  46.   
  47. //这里可以加上业务处理代码,当应用有数据发送时将数据发送到一个通道里(通道只保存数据指针),这里加上从通道获取数据指针的处理函数。
  48.     for{  
  49.         select {  
  50.         case <-ticker.C:  
  51.             ch<-1  
  52.             go ClientMsgHandler(conn,ch)  
  53.         case <-time.After(time.Second*10):  
  54.             defer conn.Close()  
  55.             fmt.Println("timeout")  
  56.         }  
  57.     }  
  58.   
  59. }  
  60.   
  61. //客户端消息处理  
  62. func ClientMsgHandler(conn net.Conn,ch chan int)  {  
  63.   
  64.     <-ch  
  65.     //获取当前时间  
  66.     msg:=time.Now().String()  
  67.     SendMsg(conn,msg)  
  68. }  
  69.   
  70. func GetSession() string{  
  71.     gs1:=time.Now().Unix()  
  72.     gs2:=strconv.FormatInt(gs1,10)  
  73.     return gs2  
  74. }  
  75.   
  76. func SendMsg(conn net.Conn,msg string)  {  
  77.   
  78. session:=GetSession()  
  79.   
  80.     words := "{\"Session\":"+session +",\"Meta\":\"Monitor\",\"Message\":\""+msg+"\"}"  
  81.     conn.Write([] byte(words))  
  82.     protocol.Enpack([]byte(words))  
  83.     conn.Write(protocol.Enpack([]byte(words)))  
  84.   
  85. }  

猜你喜欢

转载自blog.csdn.net/u014230625/article/details/80761593