golang-im聊天
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

186 行
4.3 KiB

  1. package main
  2. import (
  3. "fmt"
  4. "gim/pkg/pb"
  5. "gim/pkg/util"
  6. "log"
  7. "net"
  8. "time"
  9. gim_util "github.com/alberliu/gn/util"
  10. jsoniter "github.com/json-iterator/go"
  11. "google.golang.org/protobuf/proto"
  12. )
  13. var codecFactory = gim_util.NewHeaderLenCodecFactory(2, 1024)
  14. func main() {
  15. log.SetFlags(log.Lshortfile | log.LstdFlags)
  16. client := TcpClient{}
  17. log.Println("input UserId,DeviceId,SyncSeq")
  18. fmt.Scanf("%d %d %d", &client.UserId, &client.DeviceId, &client.Seq)
  19. client.Start()
  20. select {}
  21. }
  22. func Json(i interface{}) string {
  23. bytes, _ := jsoniter.Marshal(i)
  24. return string(bytes)
  25. }
  26. type TcpClient struct {
  27. UserId int64
  28. DeviceId int64
  29. Seq int64
  30. codec *gim_util.Codec
  31. Conn net.Conn
  32. }
  33. func (c *TcpClient) Output(pt pb.PackageType, requestId int64, message proto.Message) {
  34. var input = pb.Input{
  35. Type: pt,
  36. RequestId: requestId,
  37. }
  38. if message != nil {
  39. bytes, err := proto.Marshal(message)
  40. if err != nil {
  41. log.Println(err)
  42. return
  43. }
  44. input.Data = bytes
  45. }
  46. inputByf, err := proto.Marshal(&input)
  47. if err != nil {
  48. log.Println(err)
  49. return
  50. }
  51. _, err = c.Conn.Write(gim_util.Encode(inputByf))
  52. if err != nil {
  53. log.Println(err)
  54. }
  55. }
  56. func (c *TcpClient) Start() {
  57. //connect, err := net.Dial("tcp", "111.229.238.28:8080")
  58. //connect, err := net.Dial("tcp", "im-tcp-connect.izhyin.com:8001")
  59. connect, err := net.Dial("tcp", "im-tcp-connect.zhiyingos.com:8001")
  60. if err != nil {
  61. log.Println(err)
  62. return
  63. }
  64. c.codec = codecFactory.NewCodec(connect)
  65. c.Conn = connect
  66. c.SignIn()
  67. c.SyncTrigger()
  68. c.SubscribeRoom()
  69. go c.Heartbeat()
  70. go c.Receive()
  71. }
  72. func (c *TcpClient) SignIn() {
  73. signIn := pb.SignInInput{
  74. UserId: c.UserId,
  75. DeviceId: c.DeviceId,
  76. Token: "AIXWNMSQRYTVBOFIICDRZQYXPRHFUNTIXHVTSNVN",
  77. }
  78. c.Output(pb.PackageType_PT_SIGN_IN, time.Now().UnixNano(), &signIn)
  79. }
  80. func (c *TcpClient) SyncTrigger() {
  81. c.Output(pb.PackageType_PT_SYNC, time.Now().UnixNano(), &pb.SyncInput{Seq: c.Seq})
  82. }
  83. func (c *TcpClient) Heartbeat() {
  84. ticker := time.NewTicker(time.Minute * 5)
  85. for range ticker.C {
  86. c.Output(pb.PackageType_PT_HEARTBEAT, time.Now().UnixNano(), nil)
  87. }
  88. }
  89. func (c *TcpClient) Receive() {
  90. for {
  91. bytes, err := c.codec.Read()
  92. if err != nil {
  93. log.Println(err)
  94. return
  95. }
  96. c.HandlePackage(bytes)
  97. }
  98. }
  99. func (c *TcpClient) SubscribeRoom() {
  100. c.Output(pb.PackageType_PT_SUBSCRIBE_ROOM, 0, &pb.SubscribeRoomInput{
  101. RoomId: 1,
  102. Seq: 0,
  103. })
  104. }
  105. func (c *TcpClient) HandlePackage(bytes []byte) {
  106. var output pb.Output
  107. err := proto.Unmarshal(bytes, &output)
  108. if err != nil {
  109. log.Println(err)
  110. return
  111. }
  112. switch output.Type {
  113. case pb.PackageType_PT_SIGN_IN:
  114. log.Println(Json(&output))
  115. case pb.PackageType_PT_HEARTBEAT:
  116. log.Println("心跳响应")
  117. case pb.PackageType_PT_SYNC:
  118. log.Println("离线消息同步开始------")
  119. syncResp := pb.SyncOutput{}
  120. err := proto.Unmarshal(output.Data, &syncResp)
  121. if err != nil {
  122. log.Println(err)
  123. return
  124. }
  125. log.Println("离线消息同步响应:code", output.Code, "message:", output.Message)
  126. for _, msg := range syncResp.Messages {
  127. log.Printf("消息:发送者类型:%d 发送者id:%d 接收者类型:%d 接收者id:%d 消息内容:%+v seq:%d \n",
  128. msg.Sender.SenderType, msg.Sender.SenderId, msg.ReceiverType, msg.ReceiverId, util.FormatMessage(msg.MessageType, msg.MessageContent), msg.Seq)
  129. c.Seq = msg.Seq
  130. }
  131. ack := pb.MessageACK{
  132. DeviceAck: c.Seq,
  133. ReceiveTime: util.UnixMilliTime(time.Now()),
  134. }
  135. c.Output(pb.PackageType_PT_MESSAGE, output.RequestId, &ack)
  136. log.Println("离线消息同步结束------")
  137. case pb.PackageType_PT_MESSAGE:
  138. messageSend := pb.MessageSend{}
  139. err := proto.Unmarshal(output.Data, &messageSend)
  140. if err != nil {
  141. log.Println(err)
  142. return
  143. }
  144. msg := messageSend.Message
  145. //if msg.Sender.SenderType == 1 {
  146. // //系统发送的消息
  147. //
  148. //}
  149. log.Printf("消息:发送者类型:%d 发送者id:%d 接收者类型:%d 接收者id:%d 消息内容:%+v seq:%d \n",
  150. msg.Sender.SenderType, msg.Sender.SenderId, msg.ReceiverType, msg.ReceiverId, util.FormatMessage(msg.MessageType, msg.MessageContent), msg.Seq)
  151. c.Seq = msg.Seq
  152. ack := pb.MessageACK{
  153. DeviceAck: msg.Seq,
  154. ReceiveTime: util.UnixMilliTime(time.Now()),
  155. }
  156. c.Output(pb.PackageType_PT_MESSAGE, output.RequestId, &ack)
  157. default:
  158. log.Println("switch other")
  159. }
  160. }