用golang编写简单的Echo Server
用golang编写简单的Echo Server这段时间在看golang的网络编程方面的内容,网络知识很浅薄啊,很多东西还要不断的学习,很多也看不懂,今天先来一个简单的内容,用golang写一个简单的echo server。 TCP/IP协议大家都知道TCP/IP协议簇是当今网络世界的事实标准协议,与其对应的是OSI的七层模型,对于这七层模型这里就不再赘述了,这里只是简单介绍一下TCP/IP的四层模型。 TCP/IP的四层模型最下面是一个物理层,上面是网络层,再往上就是传输层,最后是应用层了,分层的概念相信大家都之的,这样在不同层之间变化就是打包或者解包,简单来说就是加上头信息或者去掉头信息。 golang APIgolang的net包里面有很方便的API供我们使用,这个API主要可以划分成Addr,Listen,Connection,Dialer,IP和其他的一些网络API,例如DNS API等,这里就不介绍其他的网络API(主要是自己也没有研究_)。 Addr主要有IPAddr,TCPAddr,UDPAddr和UnixAddr,主要就是不同的地址,这是网络编程的基础,没有地址就像写信不附地址,根本寄不到啊! Listener主要就是TCPListener,UnixListener(咦,为什么没有UDPListener呢?),Listener是一般是服务端需要调用的,因为服务端需要监听客户端呀,时刻看着Y的来不来跟我打招呼啊。 Connection就是连接吗,它就是两个节点沟通的桥梁啊,没有它你就跟你对象搭不上话啊。 Dialer就是请求者啊,当服务端准备好了之后,客户端就可以Dial一下了,如果顺利的话就可以拿到一个Connection,这样的话就可以跟另一端的人搭上话了。 简单的Echo Server好了,现在用一个Echo Server来简单的展示一下如何使用TCP来进行网络通信,当然你也可以用UDP。 Serverpackage main import ( "net" "os" "fmt" "io" ) const BUFF_SIZE = 1024 var buff = make([]byte,BUFF_SIZE) // 接受一个TCPConn处理内容 func handleConn(tcpConn *net.TCPConn){ if tcpConn == nil { return } for { n,err := tcpConn.Read(buff) if err == io.EOF { fmt.Printf("The RemoteAddr:%s is closed!n",tcpConn.RemoteAddr().String()) return } handleError(err) if string(buff[:n]) == "exit" { fmt.Printf("The client:%s has exitedn",tcpConn.RemoteAddr().String()) } if n > 0 { fmt.Printf("Read:%s",string(buff[:n])) } } } // 错误处理 func handleError(err error) { if err == nil { return } fmt.Printf("error:%sn",err.Error()) } func main() { if len(os.Args) != 2 { fmt.Println("Usage:<command> <port>") return } port := os.Args[1] tcpAddr,err := net.ResolveTCPAddr("tcp4","localhost:"+port) handleError(err) tcpListener,err := net.ListenTCP("tcp4",tcpAddr) //监听 handleError(err) defer tcpListener.Close() for { tcpConn,err := tcpListener.AcceptTCP() fmt.Printf("The client:%s has connected!n",tcpConn.RemoteAddr().String()) handleError(err) defer tcpConn.Close() go handleConn(tcpConn) //起一个goroutine处理 } } Clientpackage main import ( "net" "fmt" "os" "bufio" ) const BUFF_SIZE = 1024 var input = make([]byte,BUFF_SIZE) func handleError(err error) { if err == nil { return } fmt.Printf("error:%sn","localhost:"+port) handleError(err) tcpConn,err := net.DialTCP("tcp4",nil,tcpAddr) handleError(err) reader := bufio.NewReader(os.Stdin) var continued = true var inputStr string for continued { n,err := reader.Read(input) handleError(err) if n > 0 { k,_ := tcpConn.Write(input[:n]) if k > 0 { inputStr = string(input[:k]) fmt.Printf("Write:%s",inputStr) if inputStr == "exitn" { //在比对时由于有个回车符,所以加上n continued = false //也可以将inputStr = TrimRight(inputStr,"n") } } } } } 运行结果
Server wowzai@ubuntu:~/coding/gopath/gopkg$ ./server 8888 Client wowzai@ubuntu:~/coding/gopath/gopkg$ ./client 8888 恩,一个简单的Echo Server就这样了,细节做的不够好,但是大致结构是这样的。这里我用的TCP,读者也可以用UDP或者IP等。 大致就这样吧,哦,想起来上面有问为什么没有UDPListener,你想到了吗?恩恩,我相信你一定想到了,原因就是UDP协议不是面向连接的,它也不保证发出去了对方你一定能收到,它在那里只管发数据和接受数据,所以不存在UDPListener一说。
参考资料:http://jan.newmarch.name/go/arch/chapter-arch.html (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |