// 处理C2C消息转发 func HandleC2CTextChat(conn *net.TCPConn, recPacket *packet.Packet) { // read readMsg := &pb.PbC2CTextChat{} packet.Unpack(recPacket, readMsg) from_uuid := ConnMapUuid.Get(conn).(string) to_uuid := readMsg.GetToUuid() txt_msg := readMsg.GetTextMsg() // timestamp := readMsg.GetTimestamp() // 验证发送者的真实性以及发送对象是否存,若消息伪造,则断开该连接 if readMsg.GetFromUuid() != from_uuid || !cid.UuidCheckExist(to_uuid) { CloseConn(conn) return } // write writeMsg := &pb.PbC2CTextChat{ FromUuid: proto.String(from_uuid), ToUuid: proto.String(to_uuid), TextMsg: proto.String(txt_msg), Timestamp: proto.Int64(time.Now().Unix()), } // 在线消息包 pac1, err := packet.Pack(packet.PK_C2CTextChat, writeMsg) if err != nil { log.Printf("%v\r\n", err) return } // 离线消息包 pac2, err := packet.Pack(packet.PK_ServerResponseC2COfflineMsg, writeMsg) if err != nil { log.Printf("%v\r\n", err) return } // 若 to_uuid 在线,则转发该消息,发送失败 或者 to_uuid不在线 则保存为离线消息 if cid.UuidCheckOnline(to_uuid) { to_conn := UuidMapConn.Get(to_uuid).(*net.TCPConn) if SendByteStream(to_conn, pac1.GetBytes()) != nil { c2cmsg.AddMsg(to_uuid, string(pac2.GetBytes())) report.AddCount(report.OfflineMsg, 1) } else { report.AddCount(report.OnlineMsg, 1) } } else { c2cmsg.AddMsg(to_uuid, string(pac2.GetBytes())) report.AddCount(report.OfflineMsg, 1) } }
// 初始化conn func InitConn(conn *net.TCPConn, uuid string) { ConnMapLoginStatus.Set(conn, nil) UuidMapConn.Set(uuid, conn) ConnMapUuid.Set(conn, uuid) cid.UuidOnLine(uuid) report.AddCount(report.OnlineUser, 1) }
// 处理客户端之间的消息转发 func HandleC2CTextChat(conn *net.TCPConn, recPacket *packet.Packet) { // read readMsg := &pb.PbC2CTextChat{} packet.Unpack(recPacket, readMsg) from_uuid := ConnMapUuid.Get(conn).(string) to_uuid := readMsg.GetToUuid() txt_msg := readMsg.GetTextMsg() timestamp := readMsg.GetTimestamp() // 验证发送者的真实性以及发送对象是否存,若消息伪造,则断开该连接 if readMsg.GetFromUuid() != from_uuid || !dao.UuidCheckExist(to_uuid) { CloseConn(conn) return } // write writeMsg := &pb.PbC2CTextChat{ FromUuid: proto.String(from_uuid), ToUuid: proto.String(to_uuid), TextMsg: proto.String(txt_msg), Timestamp: proto.Int64(timestamp), } pac, err := packet.Pack(packet.PK_C2CTextChat, writeMsg) if err != nil { log.Printf("%v\r\n", err) return } // 若 to_uuid 在线,则转发该消息,发送失败 或者 to_uuid不在线 则保存为离线消息 if dao.UuidCheckOnline(to_uuid) { // fmt.Println("在线消息转发") to_conn := UuidMapConn.Get(to_uuid).(*net.TCPConn) if SendByteStream(to_conn, pac.GetBytes()) != nil { // fmt.Println("发送失败转离线消息保存") dao.OfflineMsgAddMsg(to_uuid, string(pac.GetBytes())) report.AddCount(report.OfflineMsg, 1) } else { report.AddCount(report.OnlineMsg, 1) } } else { // fmt.Println("不在线转离线消息保存") dao.OfflineMsgAddMsg(to_uuid, string(pac.GetBytes())) report.AddCount(report.OfflineMsg, 1) } }
func (this *Server) Start(listener *net.TCPListener) { log.Printf("Start listen on %v\r\n", listener.Addr()) this.waitGroup.Add(1) defer func() { listener.Close() this.waitGroup.Done() }() // 防止恶意连接 go this.dealSpamConn() // report记录,定时发送邮件 go report.Work() for { select { case <-this.exitCh: log.Printf("Stop listen on %v\r\n", listener.Addr()) return default: } listener.SetDeadline(time.Now().Add(this.acceptTimeout)) conn, err := listener.AcceptTCP() if err != nil { if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() { // log.Printf("Accept timeout: %v\r\n", opErr) continue } report.AddCount(report.TryConnect, 1) log.Printf("Accept error: %v\r\n", err) continue } report.AddCount(report.SuccessConnect, 1) // 连接后等待登陆验证 handlers.ConnMapLoginStatus.Set(conn, time.Now()) log.Printf("Accept: %v\r\n", conn.RemoteAddr()) go this.handleClientConn(conn) } }
// 关闭conn func CloseConn(conn *net.TCPConn) { conn.Close() ConnMapLoginStatus.Delete(conn) uuid := ConnMapUuid.Get(conn) UuidMapConn.Delete(uuid) ConnMapUuid.Delete(conn) if uuid != nil { cid.UuidOffLine(uuid.(string)) } report.AddCount(report.OnlineUser, -1) }