func getPacFromBuf(buf []byte, n int) *packet.Packet { pacLen := convert.BytesToUint32(buf[0:4]) pac := &packet.Packet{ Len: pacLen, Type: convert.BytesToUint32(buf[4:8]), Data: buf[8:pacLen], } if n != int(pacLen) { fmt.Println("Len:", pac.Len) fmt.Println("Type:", pac.Type) fmt.Println("Data:", pac.Data) fmt.Println("数据不完整") return nil } return pac }
// 模拟客户端(uuid) func testClient(uuid int) { defer func() { if e := recover(); e != nil { log.Printf("uuid: [%v] Panic: %v\r\n", getUuid(uuid), e) } }() // 连接服务器 tcpAddr, _ := net.ResolveTCPAddr("tcp4", config.Addr) conn, err := net.DialTCP("tcp", nil, tcpAddr) if err != nil { log.Printf("[%v] DialTCP失败: %v\r\n", getUuid(uuid), err) return } // 发送登陆请求 writeLoginMsg := &pb.PbClientLogin{ Uuid: proto.String(getUuid(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", getUuid(uuid), err) return } // 下面这些处理和server.go中的一样 receivePackets := make(chan *packet.Packet, 20) // 接收到的包 chStop := make(chan bool) // 通知停止消息处理 request := make([]byte, 1024) rbuf := ringbuffer.NewRingBuffer(1024) defer func() { conn.Close() chStop <- true }() // 发送心跳包 go ping(conn) // 处理接受到的包 go handlePackets(uuid, conn, receivePackets, chStop) for { readSize, err := conn.Read(request) if err != nil { return } if readSize > 0 { rbuf.Write(request[:readSize]) // 包长(4) + 类型(4) + 包体(len([]byte)) for { if rbuf.Size() >= 8 { pacLen := convert.BytesToUint32(rbuf.Bytes(4)) if rbuf.Size() >= int(pacLen) { rbuf.Peek(4) receivePackets <- &packet.Packet{ Len: pacLen, Type: convert.BytesToUint32(rbuf.Read(4)), Data: rbuf.Read(int(pacLen) - 8), } } else { break } } else { break } } } } }
func (this *Server) handleClientConn(conn *net.TCPConn) { this.waitGroup.Add(1) defer this.waitGroup.Done() receivePackets := make(chan *packet.Packet, 100) // 接收到的包 chStop := make(chan bool) // 通知停止消息处理 addr := conn.RemoteAddr().String() defer func() { defer func() { if e := recover(); e != nil { log.Printf("Panic: %v\r\n", e) } }() handlers.CloseConn(conn) log.Printf("Disconnect: %v\r\n", addr) chStop <- true }() // 处理接收到的包 go this.handlePackets(conn, receivePackets, chStop) // 接收数据 log.Printf("HandleClient: %v\r\n", addr) // 包长(4) + 类型(4) + 包体(len(pacData)) var ( bLen []byte = make([]byte, 4) bType []byte = make([]byte, 4) pacLen uint32 ) for { select { case <-this.exitCh: log.Printf("Stop handleClientConn\r\n") return default: } conn.SetReadDeadline(time.Now().Add(this.readTimeout)) 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 > this.maxPacLen { 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 } receivePackets <- &packet.Packet{ Len: pacLen, Type: convert.BytesToUint32(bType), Data: pacData, } } }
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 } } }
func (this *Server) handleClientConn(conn *net.TCPConn) { this.waitGroup.Add(1) defer this.waitGroup.Done() receivePackets := make(chan *packet.Packet, 20) // 接收到的包 chStop := make(chan bool) // 通知停止消息处理 addr := conn.RemoteAddr().String() defer func() { defer func() { if e := recover(); e != nil { log.Printf("Panic: %v\r\n", e) } }() handlers.CloseConn(conn) log.Printf("Disconnect: %v\r\n", addr) chStop <- true }() // 处理接收到的包 go this.handlePackets(conn, receivePackets, chStop) // 接收数据 log.Printf("HandleClient: %v\r\n", addr) request := this.reqMemPool.Get().([]byte) defer this.reqMemPool.Put(request) rbuf := this.rbufMemPool.Get().(*ringbuffer.RingBuffer) defer this.rbufMemPool.Put(rbuf) for { select { case <-this.exitCh: log.Printf("Stop handleClientConn\r\n") return default: } conn.SetReadDeadline(time.Now().Add(this.readTimeout)) readSize, err := conn.Read(request) if err != nil { log.Printf("Read failed: %v\r\n", err) return } if readSize > 0 { rbuf.Write(request[:readSize]) // 包长(4) + 类型(4) + 包体(len([]byte)) for { if rbuf.Size() >= 8 { pacLen := convert.BytesToUint32(rbuf.Bytes(4)) if rbuf.Size() >= int(pacLen) { rbuf.Peek(4) receivePackets <- &packet.Packet{ Len: pacLen, Type: convert.BytesToUint32(rbuf.Read(4)), Data: rbuf.Read(int(pacLen) - 8), } } else { break } } else { break } } } } }
// 模拟客户端(uuid) func testClient(uuid int) { defer func() { if e := recover(); e != nil { log.Printf("uuid: [%v] Panic: %v\r\n", getUuid(uuid), e) } }() // 连接服务器 tcpAddr, _ := net.ResolveTCPAddr("tcp4", config.Addr) conn, err := net.DialTCP("tcp", nil, tcpAddr) if err != nil { log.Printf("[%v] DialTCP失败: %v\r\n", getUuid(uuid), err) return } // 发送登陆请求 writeLoginMsg := &pb.PbClientLogin{ Uuid: proto.String(getUuid(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", getUuid(uuid), err) return } // 下面这些处理和server.go中的一样 receivePackets := make(chan *packet.Packet, 100) // 接收到的包 chStop := make(chan bool) // 通知停止消息处理 defer func() { conn.Close() chStop <- true }() // 发送心跳包 go ping(conn) // 处理接受到的包 go handlePackets(uuid, conn, receivePackets, chStop) // 包长(4) + 类型(4) + 包体(len(pacData)) var ( bLen []byte = make([]byte, 4) bType []byte = make([]byte, 4) pacLen uint32 ) for { 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 } receivePackets <- &packet.Packet{ Len: pacLen, Type: convert.BytesToUint32(bType), Data: pacData, } } }