前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【译】在 Go 语言中实现 UDP 和 TCP 网络通讯

【译】在 Go 语言中实现 UDP 和 TCP 网络通讯

作者头像
用户2131907
发布2019-02-27 13:07:14
2K0
发布2019-02-27 13:07:14
举报
文章被收录于专栏:程序猿成长计划

Go因为作为非常好用的系统编程语言而知名。开发者很喜欢它在开发后端服务时的简洁,易于开发和高性能。在很多后端服务中一个关键的特性是网络通信。有很多应用级别的协议用于软件之间通过网络进行交互。在它们的底层大都依赖于 TCP 或者 UDP。在本文中, 我们将讨论在Golang中实现UDP和TCP所涉及到的一些代码。让我们开始吧。

Go语言中的TCP

在Go语言中支持TCP已经有大量的文章和资源讲解了。显然,因为它作为互联网中广泛使用的HTTP协议的底层协议,使得它变得非常流行。 让我们看看在Go语言中使用TCP的一些实例。

首先,最重要的是Go的net包,它是在Go中任何网络通信的关键。在net包中,包含了 TCPAddrTCPConn, and TCPListener 这几个用于支持TCP的数据类型。如果你对此感兴趣,可以花一些时间去研究一下它们。在大多数情况下,除非需要访问连接的高级属性,我们并不需要直接使用这些类型。Go的net包支持一些不仅仅包含TCP,还包含其它的面向流的网络协议,比如TCP, unix或者unixpocket。这些接口是 Conn 和 Listener,我们将会简短的了解一下这两个接口。

Go语言中的UDP

在Go语言中,UDP的支持并不像TCP那样在很多博客和论坛中有很多指南。对于现代软件来说,UDP是非常重要的协议,有些情况下使用UDP作为我们的网络协议是非常合理的。

Go的net包提供了对UDP相关类型的支持,主要包含 UDPConn 和 UDPAddr。在网络上我找到的大部分例子都是直接使用这些类型,但是,在Go中有更好的方式去开发基于UDP的软件。

与TCP一样,也有很多抽象的接口用于使用UDP进行通信。最重要的是 PacketConn,它提供了对面向数据报的协议如UDP,IP或者Unix数据报的支持。

Go 语言的 UDP 和 TCP 客户端实现

现在我们开始来看看实际的代码,如果我们使用接口,那么 TCP 和 UDP 版本的实现是一致的,来看看具体代码:

TCP:

代码语言:javascript
复制
//Connect TCP
conn, err := net.Dial("tcp", "host:port")
if err != nil {
    return err
}
defer conn.Close()

//simple Read
buffer := make([]byte, 1024)
conn.Read(buffer)

//simple write
conn.Write([]byte("Hello from client"))

net.Dial() 返回 Conn 接口,支持读和写方法。Conn 支持超级受欢迎的 io.Readerio.Writer 接口,在 Go 的很多包中都有实现,例如 bufio允许缓冲 I/O 读写。

我们注意到net.Dial()有一个“tcp”的字符串参数,它用于告诉Go初始化一个tcp连接。第二个参数是目标地址。

那关于UDP客户端怎么写?猜一下!!

代码语言:javascript
复制
//Connect udp
conn, err := net.Dial("udp", "host:port")
if err != nil {
    return err
}
defer conn.Close()

//simple Read
buffer := make([]byte, 1024)
conn.Read(buffer)

//simple write
conn.Write([]byte("Hello from client"))

非常直接对吧?唯一的不同是net.Dial()函数的第一个参数不同。我们使用“udp”表明我们希望创建一个UDP连接。

GOLANG中的TCP VS UDP:服务端实现

TCP和UDP在服务端的实现是不同的。在实现TCP的时候,我们需要使用 Listener 接口 监听和接受TCP连接。让我们看一段代码:

代码语言:javascript
复制
// listen to incoming tcp connections
l, err := net.Listen("tcp", "host:port")
if err != nil {
    return err
}
defer l.Close()
// A common pattern is to start a loop to continously accept connections
for {
    //accept connections using Listener.Accept()
    c, err := l.Accept()
    if err!= nil {
        return err
    }
    //It's common to handle accepted connection on different goroutines
    go handleConnection(c)
}

代码是非常简单和直接的,只需要对TCP服务端有一些基础的理解:你需要监听来自外部的连接,然后通过在连接上读写数据处理对它进行处理。让我们看一段关于如何读写数据的最简单的代码:

代码语言:javascript
复制
func handleConnection(c net.Conn) {
    //some code...

    //Simple read from connection
    buffer := make([]byte, 1024)
    c.Read(buffer)

    //simple write to connection
    c.Write([]byte("Hello from server"))
}

现在,你注意到了吗:Listener.Accept()返回的连接是与TCP客户端一样的,都实现了 Conn 接口。对io.Reader和io.Writer的支持使它可以在很多Go的包中得到很好地兼容。

在Go中实现一个UDP服务器与TCP有些不同,它使用 PacketConn 接口取代了Conn接口和listener。让我们看一下如何实现:

代码语言:javascript
复制
// listen to incoming udp packets
pc, err := net.ListenPacket("udp", "host:port")
if err != nil {
    log.Fatal(err)
}
defer pc.Close()

//simple read
buffer := make([]byte, 1024)
pc.ReadFrom(buffer)

//simple write
pc.WriteTo([]byte("Hello from client"), addr)

对于UDP服务器来说,我们使用net.ListenPacket()方法,加上"udp"参数宣称我们准备在服务器的地址上接收UDP交互。我们之后就可以对UDP客户端进行读写了。 与类型Conn不同的是,PackerConn并不支持io.readerio.writer接口,但是它支持两个特殊的读写方法ReadFrom()WriteTo()WriteTo()方法需要提供一个参数作为发送的数据到哪个地址,ReadFrom()则返回数据是从哪个地址接收的。

本文应该可以作为在Go中实现TCP和UDP的代码实践,希望你能够学到一些新的东西。


原文:

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016-09-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Go语言中的TCP
  • Go语言中的UDP
  • Go 语言的 UDP 和 TCP 客户端实现
  • GOLANG中的TCP VS UDP:服务端实现
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档