// 通信数据编码与发送 func (self *TP) send(data *NetData) { if data.From == "" { data.From = self.uid } d, err := json.Marshal(*data) if err != nil { debug.Println("Debug: 发送数据-编码出错", err) return } conn := self.getConn(data.To) if conn == nil { debug.Printf("Debug: 发送数据-连接已断开: %+v", data) return } // 封包 end := self.Packet(d) // 发送 conn.Write(end) debug.Printf("Debug: 发送数据-成功: %+v", data) }
// 解码收到的数据并存入缓存 func (self *TP) save(conn *Connect) { debug.Printf("Debug: 收到数据-Byte: %v", conn.TmpBuffer) // 解包 dataSlice := make([][]byte, 10) dataSlice, conn.TmpBuffer = self.Unpack(conn.TmpBuffer) for _, data := range dataSlice { debug.Printf("Debug: 收到数据-解码前: %v", string(data)) d := new(NetData) err := json.Unmarshal(data, d) if err == nil { // 修复缺失请求方地址的请求 if d.From == "" { d.From = conn.Addr() } // 添加到读取缓存 self.apiReadChan <- d debug.Printf("Debug: 收到数据-NetData: %+v", d) } else { debug.Printf("Debug: 收到数据-解码错误: %v", err) } } }
// 以服务器模式启动 func (self *TP) server() { var err error retry: self.listener, err = net.Listen("tcp", self.port) if err != nil { debug.Printf("Debug: 监听端口出错: %v", err) time.Sleep(LOOP_TIMEOUT) goto retry } log.Printf(" * —— 已开启服务器监听 (port %v) ——", self.port) for self.listener != nil { // 等待下一个连接,如果没有连接,listener.Accept会阻塞 conn, err := self.listener.Accept() if err != nil { return } debug.Printf("Debug: 客户端 %v 已连接,但尚未验证身份!", conn.RemoteAddr().String()) // 开启该连接处理协程(读写两条协程) self.sGoConn(conn) } }
// 连接初始化,绑定节点与连接,默认key为节点ip func (self *TP) sInitConn(conn *Connect, remoteAddr string) (nodeuid string, usable bool) { read_len, err := conn.Read(conn.Buffer) if err != nil || read_len == 0 { return } // 解包 conn.TmpBuffer = append(conn.TmpBuffer, conn.Buffer[:read_len]...) dataSlice := make([][]byte, 10) dataSlice, conn.TmpBuffer = self.Unpack(conn.TmpBuffer) for i, data := range dataSlice { debug.Println("Debug: 收到数据-第1批-解码前: ", string(data)) d := new(NetData) json.Unmarshal(data, d) // 修复缺失请求方地址的请求 if d.From == "" { d.From = remoteAddr // 或可为:strings.Split(remoteAddr, ":")[0] } if i == 0 { debug.Printf("Debug: 收到数据-第1条-NetData: %+v", d) // 检查连接权限 if !self.checkRights(d, remoteAddr) { return } nodeuid = d.From // 添加连接到节点池 self.connPool[nodeuid] = conn // 判断是否为短链接 if d.Operation != IDENTITY { conn.Short = true } else { log.Printf(" * —— 客户端 %v (%v) 连接成功 ——", nodeuid, remoteAddr) } // 标记连接已经正式生效可用 conn.Usable = true } // 添加到读取缓存 self.apiReadChan <- d } return nodeuid, true }