package main // 提供可用服务器地址的服务器 // todo: 需要对地址池操作加访问锁 import ( "TCPServerClient/utils" "fmt" "net" "strconv" "strings" "time" ) const ( DefaultServerIP = "localhost" // 本机服务器IP DefaultServerPort = 50000 // 本机服务器端口号 DefaultRequestInfo = "Request Addr" // 请求可用服务器IP的命令字段 DefaultAuthenticationInfo = "User Authentication" // 验证用户身份的命令字段 DefaultSyncInfo = "Sync Addr" // 同步IP地址的命令字段 DefaultPassword = "12345678" // 消息加解密密码。必须是八位 ) type AddrServer struct { serverIP string // 本机服务器IP serverPort int // 本机服务器端口号 authInfo string requestInfo string syncInfo string password string addrs CanBeUsedAddrHeap // 可用服务器的地址池 nextAddrIndex int // 用于服务器地址池取用 } // 开启server,并建立监听 func (s *AddrServer) Start() { // 初始化Server fmt.Println("Starting the addr server ...") s.init() // 创建addrs清理协程 go s.verifyIPAddrList() // 创建 listener listener, err := net.Listen("tcp", s.serverIP+":"+strconv.Itoa(s.serverPort)) if err != nil { fmt.Println("Error listening", err.Error()) return } // 监听并接受来自客户端或服务器的连接,并进行处理 for { conn, err := listener.Accept() if err != nil { fmt.Println("Error accepting", err.Error()) return }else{ fmt.Println("AddrServer Accept conn form "+conn.RemoteAddr().String()) } // 处理请求 go s.doAddrServerStuff(conn) } } /** 初始化 */ func (s *AddrServer) init() { // 初始化 s.serverIP= DefaultServerIP s.serverPort= DefaultServerPort s.authInfo=DefaultAuthenticationInfo s.requestInfo=DefaultRequestInfo s.password=DefaultPassword s.syncInfo=DefaultSyncInfo s.nextAddrIndex=0 } /** 处理TCP请求 */ func (s *AddrServer) doAddrServerStuff(conn net.Conn) { for { // 读取原始数据 buf := make([]byte, 512) len, err := conn.Read(buf) if err != nil { fmt.Println("Error reading", err.Error()) return } msg:=string(buf[:len]) fmt.Println("Received raw data: %v", msg) // 解密数据为可读格式 msg=utils.DecryptMsgByDES(msg, s.password) fmt.Println("Received decrypt data: %v", msg) // 判断是何种请求,然后用不同的处理流程 if strings.HasPrefix(msg,s.authInfo) { s.doRequestStuff(conn,msg) }else if msg == s.syncInfo { s.doSyncStuff(conn) }else{ fmt.Println("Unable to handle request: %v", msg) continue } return } } /** 处理客户端请求:只对请求可用服务器地址的客户端连接进行响应 */ func (s *AddrServer) doRequestStuff(conn net.Conn,msg string) { // 向Server验证用户身份 // 读取用户证书 auth:=msg[len(s.authInfo):] // 向Server发送用户证书,验证用户身份; 验证通过,向客户端返回"true" b,err:=s.userAuthentication(auth) if !b { return }else{ _ , err = conn.Write([]byte("true")) } // 将可用服务器地址循环返回给客户端 newAddr:=s.getCanBeUsedAddr() _ , err = conn.Write([]byte(newAddr.ip)) if err != nil { fmt.Println("Error writing", err.Error()) }else{ fmt.Println("Send addr information to client successfully.") } // 关闭本次连接 _ = conn.Close() } // 取出地址池中下一个地址 func (s *AddrServer) getCanBeUsedAddr() CanBeUsedAddr{ if s.addrs.Len()>s.nextAddrIndex { s.nextAddrIndex++ return s.addrs[s.nextAddrIndex] }else{ s.nextAddrIndex=1 return s.addrs[0] } } /** 处理服务器请求:同步服务器地址 */ func (s *AddrServer) doSyncStuff(conn net.Conn) { // 取出conn地址 addrS := conn.RemoteAddr().String() cb:=CanBeUsedAddr{} cb.ip=strings.Split(addrS,":")[0] // 检测是否已经存在该地址 index := s.addrs.IsExistAddr(cb) if index>=0 { // 存在,则更新时间 s.addrs[index].updateTime=time.Now() fmt.Println("Updated addr success : "+addrS) }else{ // 不存在,则加入 s.addrs = append(s.addrs, cb) fmt.Println("Added addr success : "+addrS) } // 断开本次链接 _ = conn.Close() } /** 定期清理不可连接的IP地址。主动清理,每10s。 */ func (s *AddrServer) verifyIPAddrList() { fmt.Println("start addr timeout cleaner...") // 当系统当前时间-T_Update>=3600s时,将该IP地址及其后的IP地址全部移除IP池 for { for i := 0; i < len(s.addrs); i++ { if time.Now().Sub(s.addrs[i].updateTime)>=(time.Second*3600) { s.addrs=s.addrs[:i] } break } time.Sleep(time.Second*10) } } // todo:验证用户身份 func (s *AddrServer) userAuthentication(auth string) (bool,error){ // 与min server建立连接 //... //// 发送验证用户身份的请求给服务器 //_,err := conn.Write([]byte(utils.EncryptMsgByDES(c.authInfo,c.password))) //if err != nil { // fmt.Println("Error writing", err.Error()) // return false,err //} // //_,err = conn.Write([]byte(utils.EncryptMsgByDES(c.user.GetCertification(),c.password))) //if err != nil { // fmt.Println("Error writing", err.Error()) // return false,err //} // //// 接收验证结果 //buf := make([]byte, 512) //len,err := conn.Read(buf) //if err!=nil { // fmt.Println("Error reading", err.Error()) // return false,err //} //if string(buf[:len])=="true" { // fmt.Println("authentication success") // return true,nil //}else{ // return false,errors.New("authentication failed") //} fmt.Println("authentication success") return true,nil }