Пример #1
0
// 客户端(群主)申请解散讨论组
func HandleClientDisbandGroup(conn *net.TCPConn, recPacket *packet.Packet) {
	// read
	readMsg := &pb.PbClientDisbandGroup{}
	packet.Unpack(recPacket, readMsg)
	from_id := readMsg.GetFromUuid()
	group_id := readMsg.GetGroupId()
	// timestamp := readMsg.GetTimestamp()

	// 验证from_id确实是该conn,并且是group_id的群主
	group_name, group_owner := groupinfo.GetGroupNameAndOwner(group_id)
	if from_id != ConnMapUuid.Get(conn).(string) || group_owner != from_id {
		CloseConn(conn)
		return
	}

	// 解散讨论组
	ret := groupinfo.DisbandGroup(from_id, group_id)
	tips_msg := "解散讨论组[" + group_name + "]成功"
	if ret {
		tips_msg = "解散讨论组[" + group_name + "]失败"
	}

	// write
	writeMsg := &pb.PbServerNotifyDisbandGroup{
		Disband:   proto.Bool(ret),
		GroupId:   proto.String(group_id),
		GroupName: proto.String(group_name),
		TipsMsg:   proto.String(tips_msg),
		Timestamp: proto.Int64(time.Now().Unix()),
	}
	SendPbData(conn, packet.PK_ServerNotifyDisbandGroup, writeMsg)
}
Пример #2
0
// 客户端申请加入讨论组
func HandleClientJoinGroup(conn *net.TCPConn, recPacket *packet.Packet) {
	// read
	readMsg := &pb.PbClientJoinGroup{}
	packet.Unpack(recPacket, readMsg)

	from_uuid := readMsg.GetFromUuid()
	group_id := readMsg.GetGroupId()
	// note_msg := readMsg.GetNoteMsg()
	// timestamp := readMsg.GetTimestamp()

	// 加入讨论组
	if ret := groupinfo.JoinGroup(from_uuid, group_id); !ret {
		return
	}

	group_name, _ := groupinfo.GetGroupNameAndOwner(group_id)

	// write
	writeMsg := pb.PbServerNotifyJoinGroup{
		ApplicantUuid: proto.String(from_uuid),
		GroupId:       proto.String(group_id),
		GroupName:     proto.String(group_name),
		Timestamp:     proto.Int64(time.Now().Unix()),
	}

	// 通知所有组员,这个消息不离线存储
	group_members := groupinfo.GetAllUuid(group_id)
	for i := 1; i < len(group_members); i++ {
		SendPbData(UuidMapConn.Get(group_members[i]).(*net.TCPConn), packet.PK_ServerNotifyJoinGroup, writeMsg)
	}
}
Пример #3
0
// 客户端申请建立讨论组
func HandleClientBuildGroup(conn *net.TCPConn, recPacket *packet.Packet) {
	// read
	readMsg := &pb.PbClientBuildGroup{}
	packet.Unpack(recPacket, readMsg)
	uuid := ConnMapUuid.Get(conn).(string)
	group_name := readMsg.GetGroupName()

	// 建立讨论组
	ret, group_id := groupinfo.BuildGroup(group_name, uuid)
	tips_msg := "讨论组[" + group_name + "]建立成功"
	if ret {
		tips_msg = "讨论组[" + group_name + "]建立失败"
	}

	// write
	writeMsg := &pb.PbServerNotifyBuildGroup{
		Build:     proto.Bool(ret),
		GroupId:   proto.String(group_id),
		GroupName: proto.String(group_name),
		OwnerUuid: proto.String(uuid),
		TipsMsg:   proto.String(tips_msg),
		Timestamp: proto.Int64(time.Now().Unix()),
	}
	SendPbData(conn, packet.PK_ServerNotifyBuildGroup, writeMsg)
}
Пример #4
0
// 客户端请求获取讨论组信息
func HandleClientRequestGroupInfo(conn *net.TCPConn, recPacket *packet.Packet) {
	readMsg := &pb.PbClientRequestGroupInfo{}
	packet.Unpack(recPacket, readMsg)

	uuid := readMsg.GetFromUuid()
	// timestamp := readMsg.GetTimestamp()

	groupids := groupinfo.GetAllGroup(uuid)

	var allGroupInfo []*pb.PbGroupInfo

	for _, group_id := range groupids {
		s := groupinfo.GetAllUuid(group_id)
		group_name, owner_uuid, member_uuid := s[0], s[1], s[2:]

		gi := &pb.PbGroupInfo{
			GroupId:    proto.String(group_id),
			GroupName:  proto.String(group_name),
			OwnerUuid:  proto.String(owner_uuid),
			MemberUuid: member_uuid,
		}

		allGroupInfo = append(allGroupInfo, gi)
	}

	// write
	writeMsg := &pb.PbServerResponseGroupInfo{
		FromUuid:     proto.String(uuid),
		AllGroupInfo: allGroupInfo,
		Timestamp:    proto.Int64(time.Now().Unix()),
	}
	SendPbData(conn, packet.PK_ServerResponseGroupInfo, writeMsg)
}
Пример #5
0
// 客户端登陆
func HandleClientLogin(conn *net.TCPConn, recPacket *packet.Packet) {
	// read
	readMsg := &pb.PbClientLogin{}
	packet.Unpack(recPacket, readMsg)

	uuid := readMsg.GetUuid()

	// 检测uuid合法性
	if cid.UuidCheckExist(uuid) {
		// 如果已经在线则关闭以前的conn
		if cid.UuidCheckOnline(uuid) {
			co := UuidMapConn.Get(uuid)
			if co != nil {
				CloseConn(co.(*net.TCPConn))
			}
		}
		// 上线conn
		InitConn(conn, uuid)
	} else {
		CloseConn(conn)
	}

	// fmt.Println("uuid:", readMsg.GetUuid())
	// fmt.Println("version:", readMsg.GetVersion())
	// fmt.Println("timestamp:", convert.TimestampToTimeString(readMsg.GetTimestamp()))

	// write
	writeMsg := &pb.PbServerAcceptLogin{
		Login:     proto.Bool(true),
		TipsMsg:   proto.String("登陆成功"),
		Timestamp: proto.Int64(time.Now().Unix()),
	}
	SendPbData(conn, packet.PK_ServerAcceptLogin, writeMsg)
}
Пример #6
0
// 处理心跳
func HandleClientPing(conn *net.TCPConn, recPacket *packet.Packet) {
	// read
	readMsg := &pb.PbClientPing{}
	packet.Unpack(recPacket, readMsg)

	// fmt.Println("ping:", readMsg.GetPing())
	// fmt.Println("timestamp:", convert.TimestampToTimeString(readMsg.GetTimestamp()))
}
Пример #7
0
// 客户端下线
func HandleClientLogout(conn *net.TCPConn, recPacket *packet.Packet) {
	// read
	readMsg := &pb.PbClientLogout{}
	packet.Unpack(recPacket, readMsg)

	// fmt.Println("logout:", readMsg.GetLogout())
	// fmt.Println("timestamp:", convert.TimestampToTimeString(readMsg.GetTimestamp()))
	CloseConn(conn)
}
Пример #8
0
// 处理讨论组消息转发
func HandleGroupTextChat(conn *net.TCPConn, recPacket *packet.Packet) {
	// read
	readMsg := &pb.PbGroupTextChat{}
	packet.Unpack(recPacket, readMsg)

	from_uuid := ConnMapUuid.Get(conn).(string)
	group_id := readMsg.GetGroupId()
	txt_msg := readMsg.GetTextMsg()
	// timestamp := readMsg.GetTimestamp()

	// 验证发送者,这样会影响性能,视情况可以把这个验证去掉
	if readMsg.GetFromUuid() != from_uuid || !groupinfo.ExistUuidFromGroup(group_id, from_uuid) {
		CloseConn(conn)
		return
	}

	// write
	writeMsg := &pb.PbGroupTextChat{
		FromUuid:  proto.String(from_uuid),
		GroupId:   proto.String(group_id),
		TextMsg:   proto.String(txt_msg),
		Timestamp: proto.Int64(time.Now().Unix()),
	}

	// 在线消息包
	pac1, err := packet.Pack(packet.PK_GroupTextChat, writeMsg)
	if err != nil {
		log.Printf("%v\r\n", err)
		return
	}

	// 离线消息包
	pac2, err := packet.Pack(packet.PK_ServerResponseGroupOfflineMsg, writeMsg)
	if err != nil {
		log.Printf("%v\r\n", err)
		return
	}

	// 将消息转发给所有组员(除了自己),不在线则离线存储
	group_members := groupinfo.GetAllUuid(group_id)
	for i := 1; i < len(group_members); i++ {
		if group_members[i] == from_uuid {
			continue
		}

		if cid.UuidCheckOnline(group_members[i]) {
			to_conn := UuidMapConn.Get(group_members[i]).(*net.TCPConn)
			SendByteStream(to_conn, pac1.GetBytes())
		} else {
			groupmsg.AddMsg(group_members[i], string(pac2.GetBytes()))
		}
	}

}
Пример #9
0
// 处理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)
	}
}
Пример #10
0
// 处理登陆
func HandleClientLogin(conn *net.TCPConn, recPacket *packet.Packet) {
	// read
	readMsg := &pb.PbClientLogin{}
	packet.Unpack(recPacket, readMsg)

	uuid := readMsg.GetUuid()

	// 检测uuid合法性
	if cid.UuidCheckExist(uuid) {
		// 如果已经在线则关闭以前的conn
		if cid.UuidCheckOnline(uuid) {
			co := UuidMapConn.Get(uuid)
			if co != nil {
				CloseConn(co.(*net.TCPConn))
			}
		}
		// 上线conn
		InitConn(conn, uuid)
	} else {
		CloseConn(conn)
	}

	// fmt.Println("uuid:", readMsg.GetUuid())
	// fmt.Println("version:", readMsg.GetVersion())
	// fmt.Println("timestamp:", convert.TimestampToTimeString(readMsg.GetTimestamp()))

	// write
	writeMsg := &pb.PbServerAcceptLogin{
		Login:     proto.Bool(true),
		TipsMsg:   proto.String("登陆成功"),
		Timestamp: proto.Int64(time.Now().Unix()),
	}
	SendPbData(conn, packet.PK_ServerAcceptLogin, writeMsg)

	// 检查是否有该uuid的离线消息存在,若有,则发送其离线消息
	if offmsgNum := c2c.GetMsgNum(uuid); offmsgNum > 0 {
		// 这里比较复杂,后续再优化(可以多个离线消息一起发送)
		// 得到所有离线消息
		// fmt.Println("转发离线消息")
		msgs := c2c.GetMsgs(uuid, offmsgNum)
		c2c.DeleteMsgs(uuid, offmsgNum, offmsgNum)
		for i, _ := range msgs {
			SendByteStream(conn, []byte(msgs[i]))
		}
	}
}
Пример #11
0
// 客户端请求C2C离线消息
func HandleClientRequestC2COfflineMsg(conn *net.TCPConn, recPacket *packet.Packet) {
	readMsg := &pb.PbClientRequestC2COfflineMsg{}
	packet.Unpack(recPacket, readMsg)

	uuid := readMsg.GetFromUuid()

	// 检查是否有该uuid的离线消息存在,若有,则发送其离线消息
	if offmsgNum := c2cmsg.GetMsgNum(uuid); offmsgNum > 0 {
		// 这里比较复杂,后续再优化(可以多个离线消息一起发送)
		// 暂时将所有离线消息单独发送
		msgs := c2cmsg.GetMsgs(uuid, offmsgNum)
		c2cmsg.DeleteMsgs(uuid, offmsgNum, offmsgNum)
		for i, _ := range msgs {
			SendByteStream(conn, []byte(msgs[i]))
		}
	}
}
Пример #12
0
// 处理客户端之间的消息转发
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)
	}
}
Пример #13
0
// 处理收发数据包
func handlePackets(uuid int, conn *net.TCPConn, receivePackets <-chan *packet.Packet, chStop <-chan bool) {
	defer func() {
		if e := recover(); e != nil {
			log.Printf("Panic: %v\r\n")
		}
	}()
	for {
		select {
		case <-chStop:
			return

		// 消息包处理
		case p := <-receivePackets:
			if p.Type == packet.PK_ServerAcceptLogin { // 登陆回复
				// read
				readMsg := &pb.PbServerAcceptLogin{}
				packet.Unpack(p, readMsg)
				if readMsg.GetLogin() == true {
					log.Printf("[%v]: [%v]---[%v]\r\n", getUuid(uuid), readMsg.GetTipsMsg(), convert.TimestampToTimeString(readMsg.GetTimestamp()))
				}

				// write,随机向10个人发送消息
				for i := 0; i < 10; i++ {
					rand.Seed(time.Now().UnixNano())
					to_uuid := rand.Intn(total) + 1 // [1, total]
					if to_uuid == uuid {
						continue
					}

					writeMsg := &pb.PbC2CTextChat{
						FromUuid:  proto.String(getUuid(uuid)),
						ToUuid:    proto.String(getUuid(to_uuid)),
						TextMsg:   proto.String(strings.Repeat("hello,世界!!!", 100)),
						Timestamp: proto.Int64(time.Now().Unix()),
					}
					handlers.SendPbData(conn, packet.PK_C2CTextChat, writeMsg)
				}

			} else if p.Type == packet.PK_C2CTextChat { // 普通消息
				// read
				readMsg := &pb.PbC2CTextChat{}
				packet.Unpack(p, readMsg)
				from_uuid := readMsg.GetFromUuid()
				to_uuid := readMsg.GetToUuid()
				txt_msg := readMsg.GetTextMsg()
				timestamp := readMsg.GetTimestamp()
				if to_uuid != getUuid(uuid) {
					log.Printf("[%v]收到[%v]发来的不属于自己的包,该包应该属于[%v]\r\n", getUuid(uuid), from_uuid, to_uuid)
				} else {
					log.Printf("[%v]:[%v]收到来自[%v]的消息: [%v]", convert.TimestampToTimeString(timestamp), getUuid(uuid), from_uuid, txt_msg)

					// write, 回复时在原基础上加点消息,控制长度范围
					var to_txt_msg string
					var add_txt string = " 你好 hello world"

					if len(txt_msg)+len(add_txt) <= 2048 {
						to_txt_msg = txt_msg + add_txt
					} else {
						to_txt_msg = txt_msg
					}

					writeMsg := &pb.PbC2CTextChat{
						FromUuid:  proto.String(getUuid(uuid)),
						ToUuid:    proto.String(from_uuid),
						TextMsg:   proto.String(to_txt_msg),
						Timestamp: proto.Int64(time.Now().Unix()),
					}
					handlers.SendPbData(conn, packet.PK_C2CTextChat, writeMsg)
				}

			} else {
				log.Printf("[%v]收到未知包\r\n", getUuid(uuid))
			}
		}
	}
}
Пример #14
0
func testBB(i_uuid string) {
	tcpAddr, _ := net.ResolveTCPAddr("tcp4", config.Addr)
	conn, err := net.DialTCP("tcp", nil, tcpAddr)
	if err != nil {
		log.Printf("%v DialTCP失败: %v\r\n", i_uuid, err)
		return
	}
	defer conn.Close()

	// 登陆
	// write
	writeLoginMsg := &pb.PbClientLogin{
		Uuid:      proto.String(i_uuid),
		Version:   proto.Float32(3.14),
		Timestamp: proto.Int64(time.Now().Unix()),
	}
	err = handlers.SendPbData(conn, packet.PK_ClientLogin, writeLoginMsg)
	if err != nil {
		log.Printf("%v 发送登陆包失败: %v\r\n", i_uuid, err)
		return
	}

	var (
		bLen   []byte = make([]byte, 4)
		bType  []byte = make([]byte, 4)
		pacLen uint32
	)

	// read
	if n, err := io.ReadFull(conn, bLen); err != nil && n != 4 {
		log.Printf("Read pacLen failed: %v\r\n", err)
		return
	}
	if n, err := io.ReadFull(conn, bType); err != nil && n != 4 {
		log.Printf("Read pacType failed: %v\r\n", err)
		return
	}
	if pacLen = convert.BytesToUint32(bLen); pacLen > uint32(2048) {
		log.Printf("pacLen larger than maxPacLen\r\n")
		return
	}
	pacData := make([]byte, pacLen-8)
	if n, err := io.ReadFull(conn, pacData); err != nil && n != int(pacLen) {
		log.Printf("Read pacData failed: %v\r\n", err)
		return
	}
	pac := &packet.Packet{
		Len:  pacLen,
		Type: convert.BytesToUint32(bType),
		Data: pacData,
	}

	readAccepLoginMsg := &pb.PbServerAcceptLogin{}
	err = packet.Unpack(pac, readAccepLoginMsg)
	if err != nil {
		log.Printf("%v Unpack error: %v\r\n", i_uuid, err)
		return
	}
	fmt.Println(readAccepLoginMsg.GetLogin())
	fmt.Println(readAccepLoginMsg.GetTipsMsg())
	fmt.Println(convert.TimestampToTimeString(readAccepLoginMsg.GetTimestamp()))

	// 定时发送心跳包
	go ping(conn)

	// 先向对方发送消息
	// write
	go func() {
		writeC2CMsg := &pb.PbC2CTextChat{
			FromUuid:  proto.String(i_uuid),
			ToUuid:    proto.String(u_uuid),
			TextMsg:   proto.String("hi, 我的uuid是: " + i_uuid),
			Timestamp: proto.Int64(time.Now().Unix()),
		}
		err := handlers.SendPbData(conn, packet.PK_C2CTextChat, writeC2CMsg)
		if err != nil {
			log.Printf("%v 发送消息失败: %v\r\n", i_uuid, err)
			return
		}
	}()

	// 死循环,接收消息和发送消息
	for {
		fmt.Println("坐等消息到来...")
		// read
		if n, err := io.ReadFull(conn, bLen); err != nil && n != 4 {
			log.Printf("Read pacLen failed: %v\r\n", err)
			return
		}
		if n, err := io.ReadFull(conn, bType); err != nil && n != 4 {
			log.Printf("Read pacType failed: %v\r\n", err)
			return
		}
		if pacLen = convert.BytesToUint32(bLen); pacLen > uint32(2048) {
			log.Printf("pacLen larger than maxPacLen\r\n")
			return
		}
		pacData := make([]byte, pacLen-8)
		if n, err := io.ReadFull(conn, pacData); err != nil && n != int(pacLen) {
			log.Printf("Read pacData failed: %v\r\n", err)
			return
		}
		pac := &packet.Packet{
			Len:  pacLen,
			Type: convert.BytesToUint32(bType),
			Data: pacData,
		}
		readC2CMsg := &pb.PbC2CTextChat{}
		err = packet.Unpack(pac, readC2CMsg)
		if err != nil {
			log.Printf("%v 读取到的消息Unpack error: %v\r\n", i_uuid, err)
			return
		}

		from_uuid := readC2CMsg.GetFromUuid()
		to_uuid := readC2CMsg.GetToUuid()
		txt_msg := readC2CMsg.GetTextMsg()
		timestamp := readC2CMsg.GetTimestamp()

		fmt.Println("from_uuid:", from_uuid)
		fmt.Println("to_uuid:", to_uuid)
		fmt.Println("txt_msg:", txt_msg)
		fmt.Println("timestamp:", convert.TimestampToTimeString(timestamp))

		time.Sleep(5 * time.Second)

		// write
		writeC2CMsg := &pb.PbC2CTextChat{
			FromUuid:  proto.String(to_uuid),
			ToUuid:    proto.String(from_uuid),
			TextMsg:   proto.String(txt_msg + "我是 " + i_uuid),
			Timestamp: proto.Int64(timestamp),
		}
		err = handlers.SendPbData(conn, packet.PK_C2CTextChat, writeC2CMsg)
		if err != nil {
			log.Printf("%v 回复消息失败: %v\r\n", i_uuid, err)
			return
		}
	}
}
Пример #15
0
// 处理登陆
func HandleClientLogin(conn *net.TCPConn, recPacket *packet.Packet) {
	// read
	readMsg := &pb.PbClientLogin{}
	packet.Unpack(recPacket, readMsg)

	uuid := readMsg.GetUuid()

	// 检测uuid合法性
	if dao.UuidCheckExist(uuid) {
		// 如果已经在线则关闭以前的conn
		if dao.UuidCheckOnline(uuid) {
			co := UuidMapConn.Get(uuid)
			if co != nil {
				CloseConn(co.(*net.TCPConn))
			}
		}
		// 上线conn
		InitConn(conn, uuid)
	} else {
		CloseConn(conn)
	}

	// fmt.Println("uuid:", readMsg.GetUuid())
	// fmt.Println("version:", readMsg.GetVersion())
	// fmt.Println("timestamp:", convert.TimestampToTimeString(readMsg.GetTimestamp()))

	// write
	writeMsg := &pb.PbServerAcceptLogin{
		Login:     proto.Bool(true),
		TipsMsg:   proto.String("登陆成功"),
		Timestamp: proto.Int64(time.Now().Unix()),
	}
	SendPbData(conn, packet.PK_ServerAcceptLogin, writeMsg)

	// 检查是否有该uuid的离线消息存在,若有,则发送其离线消息
	if dao.OfflineMsgCheck(uuid) {
		// 这里比较复杂,后续再优化(可以多个离线消息一起发送)
		// 得到所有离线消息的id
		msgids := dao.OfflineMsgGetIds(uuid)
		// fmt.Println(uuid, "有离线消息,数量为:", len(msgids))
		var (
			k   int
			err error
		)
		for k, _ = range msgids {
			if err = SendByteStream(conn, []byte(dao.IdMsgGetMsgFromId(msgids[k]))); err != nil {
				break
			}
			// fmt.Println("正在发送离线消息", k, err, dao.IdMsgGetMsgFromId(msgids[k]))
		}

		if err != nil {
			if k != 0 {
				dao.OfflineMsgDeleteIds(uuid, msgids[k-1])
			}
		} else {
			dao.OfflineMsgDeleteIds(uuid, msgids[k])
		}
	} else {
		// fmt.Println("没有离线消息")
	}

}
Пример #16
0
func testBB(i_uuid string) {
	tcpAddr, _ := net.ResolveTCPAddr("tcp4", config.Addr)
	conn, err := net.DialTCP("tcp", nil, tcpAddr)
	if err != nil {
		log.Printf("%v DialTCP失败: %v\r\n", i_uuid, err)
		return
	}
	defer conn.Close()

	// 登陆
	// write
	writeLoginMsg := &pb.PbClientLogin{
		Uuid:      proto.String(i_uuid),
		Version:   proto.Float32(3.14),
		Timestamp: proto.Int64(time.Now().Unix()),
	}
	err = handlers.SendPbData(conn, packet.PK_ClientLogin, writeLoginMsg)
	if err != nil {
		log.Printf("%v 发送登陆包失败: %v\r\n", i_uuid, err)
		return
	}
	// read
	buf := make([]byte, 1024)
	n, err := conn.Read(buf)
	if err != nil {
		log.Printf("%v 登陆回应包读取失败: %v\r\n", i_uuid, err)
		return
	}
	pac := getPacFromBuf(buf, n)
	readAccepLoginMsg := &pb.PbServerAcceptLogin{}
	err = packet.Unpack(pac, readAccepLoginMsg)
	if err != nil {
		log.Printf("%v Unpack error: %v\r\n", i_uuid, err)
		return
	}
	fmt.Println(readAccepLoginMsg.GetLogin())
	fmt.Println(readAccepLoginMsg.GetTipsMsg())
	fmt.Println(convert.TimestampToTimeString(readAccepLoginMsg.GetTimestamp()))

	// 定时发送心跳包
	go ping(conn)

	// 先向对方发送消息
	// write
	go func() {
		writeC2CMsg := &pb.PbC2CTextChat{
			FromUuid:  proto.String(i_uuid),
			ToUuid:    proto.String(u_uuid),
			TextMsg:   proto.String("hi, 我的uuid是: " + i_uuid),
			Timestamp: proto.Int64(time.Now().Unix()),
		}
		err := handlers.SendPbData(conn, packet.PK_C2CTextChat, writeC2CMsg)
		if err != nil {
			log.Printf("%v 发送消息失败: %v\r\n", i_uuid, err)
			return
		}
	}()

	// 死循环,接收消息和发送消息
	recBuf := make([]byte, 1024)
	for {
		fmt.Println("坐等消息到来...")
		// read
		n, err := conn.Read(recBuf)
		if err != nil {
			log.Printf("%v 读取消息失败: %v\r\n", i_uuid, err)
			return
		}
		fmt.Println("消息读取完毕")
		pac := getPacFromBuf(recBuf, n)
		readC2CMsg := &pb.PbC2CTextChat{}
		err = packet.Unpack(pac, readC2CMsg)
		if err != nil {
			log.Printf("%v 读取到的消息Unpack error: %v\r\n", i_uuid, err)
			return
		}

		from_uuid := readC2CMsg.GetFromUuid()
		to_uuid := readC2CMsg.GetToUuid()
		txt_msg := readC2CMsg.GetTextMsg()
		timestamp := readC2CMsg.GetTimestamp()

		fmt.Println("from_uuid:", from_uuid)
		fmt.Println("to_uuid:", to_uuid)
		fmt.Println("txt_msg:", txt_msg)
		fmt.Println("timestamp:", convert.TimestampToTimeString(timestamp))

		time.Sleep(5 * time.Second)

		// write
		writeC2CMsg := &pb.PbC2CTextChat{
			FromUuid:  proto.String(to_uuid),
			ToUuid:    proto.String(from_uuid),
			TextMsg:   proto.String(txt_msg + "我是 " + i_uuid),
			Timestamp: proto.Int64(timestamp),
		}
		err = handlers.SendPbData(conn, packet.PK_C2CTextChat, writeC2CMsg)
		if err != nil {
			log.Printf("%v 回复消息失败: %v\r\n", i_uuid, err)
			return
		}
	}
}