func (this *Agent) Run() { this.LoadRegIds() conn, err := net.DialTCP("tcp", nil, this.serverAddr) if err != nil { log.Errorf("Dial %v error: %s", this.serverAddr, err.Error()) log.Flush() os.Exit(1) return } defer func() { conn.Close() }() dataInit := packet.PktDataInit{ DevId: this.deviceId, } initPkt, err := packet.Pack(packet.PKT_Init, 0, dataInit) if err != nil { log.Error("Pack error: %s", err.Error()) return } b, err := initPkt.Serialize() if err != nil { log.Error("Serialize error: %s", err.Error()) } log.Debug(string(initPkt.Data)) conn.Write(b) go func() { timer := time.NewTicker(20 * time.Second) hbPkt, _ := packet.Pack(packet.PKT_Heartbeat, 0, nil) heartbeat, _ := hbPkt.Serialize() for { select { //case <- done: // break case pkt := <-this.outPkt: b, err := pkt.Serialize() if err != nil { log.Errorf("Serialize error: %s", err.Error()) } log.Debugf("Write data: %s\n", b) conn.Write(b) case <-timer.C: conn.Write(heartbeat) } } }() var bufHeader = make([]byte, packet.PKT_HEADER_SIZE) for { //// check if we are exiting //select { //case <-this.exitChan: // log.Printf("Closing connection from %s.\n", conn.RemoteAddr().String()) // return //default: // // continue read //} const readTimeout = 300 * time.Second conn.SetReadDeadline(time.Now().Add(readTimeout)) // read the packet header nbytes, err := io.ReadFull(conn, bufHeader) if err != nil { if err == io.EOF { log.Warn("read EOF, closing connection") return } else if netErr, ok := err.(net.Error); ok && netErr.Timeout() { // just read timeout, not an error continue } log.Errorf("read error: %s\n", err.Error()) return } log.Debugf("%d bytes packet header read\n", nbytes) var pkt = packet.Pkt{ Data: nil, } pkt.Header.Deserialize(bufHeader) // read the packet data if pkt.Header.Len > 0 { log.Debugf("expecting data size: %d\n", pkt.Header.Len) var bufData = make([]byte, pkt.Header.Len) nbytes, err := io.ReadFull(conn, bufData) if err != nil { if err == io.EOF { log.Warn("read EOF, closing connection") return } else if netErr, ok := err.(net.Error); ok && netErr.Timeout() { // read timeout //TODO: exit? log.Errorf("Timeout on receiving packet data. error: %s\n", err.Error()) continue } log.Errorf("Error on receiving packet data. error: %s\n", err.Error()) return } log.Debugf("%d bytes packet data read: %s\n", nbytes, bufData) pkt.Data = bufData } this.handlePacket(&pkt) } }
func (this *TcpServer) handleConn(conn *net.TCPConn) { this.waitGroup.Add(1) log.Printf("New conn accepted from %s\n", conn.RemoteAddr().String()) var ( client *Client = nil ) var bufHeader = make([]byte, packet.PKT_HEADER_SIZE) for { // check if we are exiting select { case <-this.exitChan: log.Printf("Closing connection from %s.\n", conn.RemoteAddr().String()) goto Out default: // continue read } const readTimeout = 30 * time.Second conn.SetReadDeadline(time.Now().Add(readTimeout)) // read the packet header nbytes, err := io.ReadFull(conn, bufHeader) if err != nil { if err == io.EOF { log.Printf("read EOF, closing connection") goto Out } else if netErr, ok := err.(net.Error); ok && netErr.Timeout() { // just read timeout, not an error continue } log.Printf("read error: %s\n", err.Error()) continue } log.Printf("%d bytes packet header read\n", nbytes) var pkt = packet.Pkt{ Data: nil, } pkt.Header.Deserialize(bufHeader) // read the packet data if pkt.Header.Len > 0 { log.Printf("expecting data size: %d\n", pkt.Header.Len) //FIXME: check the Len var bufData = make([]byte, pkt.Header.Len) nbytes, err := io.ReadFull(conn, bufData) if err != nil { if err == io.EOF { log.Printf("read EOF, closing connection") goto Out } else if netErr, ok := err.(net.Error); ok && netErr.Timeout() { // read timeout //TODO log.Printf("read error: %s\n", err.Error()) continue } log.Printf("read error: %s\n", err.Error()) continue } log.Printf("%d bytes packet data read: %s\n", nbytes, bufData) pkt.Data = bufData } if pkt.Header.Type == packet.PKT_Init { client = HandleInit(conn, &pkt) if client == nil { goto Out } } else { this.handlePacket(client, &pkt) } } Out: conn.Close() if client != nil { ClientMapLock.Lock() delete(ClientMap, client.Id) ClientMapLock.Unlock() } this.waitGroup.Done() }