分享
  1. 首页
  2. 文章

用golang编写简单的Echo Server

wowzai · · 9618 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

用golang编写简单的Echo Server

这段时间在看golang的网络编程方面的内容,网络知识很浅薄啊,很多东西还要不断的学习,很多也看不懂,今天先来一个简单的内容,用golang写一个简单的echo server。

TCP/IP协议

大家都知道TCP/IP协议簇是当今网络世界的事实标准协议,与其对应的是OSI的七层模型,对于这七层模型这里就不再赘述了,这里只是简单介绍一下TCP/IP的四层模型。

Alt Text

TCP/IP的四层模型最下面是一个物理层,上面是网络层,再往上就是传输层,最后是应用层了,分层的概念相信大家都之的,这样在不同层之间变化就是打包或者解包,简单来说就是加上头信息或者去掉头信息。

golang API

golang的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。

Server

 package 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 exited\n",tcpConn.RemoteAddr().String())
 }
 if n > 0 {
 fmt.Printf("Read:%s",string(buff[:n]))
 }
 }
 }
 // 错误处理
 func handleError(err error) {
 if err == nil {
 return
 }
 fmt.Printf("error:%s\n",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处理
 }
 }

Client

 package 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:%s\n",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)
 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 == "exit\n" { //在比对时由于有个回车符,所以加上\n
 continued = false //也可以将inputStr = TrimRight(inputStr,"\n")
 }
 }
 }
 }
 }

运行结果

Server

wowzai@ubuntu:~/coding/gopath/gopkg$ ./server 8888
The client:127.0.0.1:34693 has connected!
Read:hello
Read:你好
Read:exit
The RemoteAddr:127.0.0.1:34693 is closed! LocalAddr:127.0.0.1:8888

Client

wowzai@ubuntu:~/coding/gopath/gopkg$ ./client 8888
hello
Write:hello
你好
Write:你好
exit
Write:exit

恩,一个简单的Echo Server就这样了,细节做的不够好,但是大致结构是这样的。这里我用的TCP,读者也可以用UDP或者IP等。

大致就这样吧,哦,想起来上面有问为什么没有UDPListener,你想到了吗?恩恩,我相信你一定想到了,原因就是UDP协议不是面向连接的,它也不保证发出去了对方你一定能收到,它在那里只管发数据和接受数据,所以不存在UDPListener一说。


参考资料: http://jan.newmarch.name/go/arch/chapter-arch.html



有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:wowzai

查看原文:用golang编写简单的Echo Server

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
9618 次点击
1 回复 | 直到 2000年01月01日 00:00:00
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏