工作的原因接触到socket,要使用socket实现一个长连接。之前只在C/C++上用过socket,而且在学校的时候也只是简单的做聊天室小程序,并没有涉及到长连接。突然用到工作项目上,心里还是有点悬的,毕竟网上的资料也不是很多。这里就一步一步记录下学习的过程、遇到的问题以及最重要的——解决问题的方法。

一、说明

golang中的socket需要用到net包,里面封装好了很多常用的函数方法以及元素类型。而且无需像C一样要经历socket,bind,listen,accept等等流程,只需要简单的几步流程就能完成,非常方便。

二、IP类型

net包中定义的ip类型直接就是byte数组:

type IP []byte

我们可以使用func parseIP(s string) IP 来把一个ip地址转换成IP类型:

ipAddr := "192.168.1.79"
addr := net.ParseIP(ipAddr)
if addr == nil{
    fmt.Println("unavaliable addr")
}else{
    fmt.Println(addr.To16())
}

三、函数

3.1 funcResolveTCPAddr(net, addr string) (*TCPAddr, error)

ResolveTCPAddr 函数的功能是解析TCP连接的地址,包含ipport

  • nettcp tcp4 tcp6三选一,分别表示TCPv4,TCPv6和任意,默认是tcp4
  • addr:主机的地址,可以是[ip+port],也可以是[domain+port],可以省略主机部分,表示本机地址

返回一个*TCPAddr 类型 ,表示一个TCP连接地址:

type TCPAddr struct {
    IP   IP
    Port int
    Zone string // IPv6 scoped addressing zone
}

3.2 func ResolveIPAddr(net, addr string) (*IPAddr, error)

ResolveIPAddr 函数的功能是解析ip地址:

  • netip  ip4 ip6 分别代表IPv4,IPv6以及任意。默认留空表示ip4
  • addr :IP地址 返回一个*IPAddr 结构:
type IPAddr struct {
    IP   IP
    Zone string // IPv6 scoped addressing zone
}

3.3 func Dial(network, address string) (Conn, error)

Dial 函数的功能是建立一个连接:

  • network: 如果是TCP连接,对应tcp tcp4 tcp6;如果是IP连接,对应ip ip4 ip6。对于ip连接,需要在后面加一个冒号然后注明协议号或者协议名字
  • address:连接的地址,ip+portdomain+port 形式,也可以省略主机地址表示本地地址217.0.0.1
    返回一个net.Conn 接口对象,包含了连接的信息,我们可以使用该对象的Write()Read() 对连接进行读写。
type Conn interface {
    Read(b []byte) (n int, err error)
    Write(b []byte) (n int, err error)
    Close() error
    LocalAddr() Addr
    RemoteAddr() Addr
    SetDeadline(t time.Time) error
    SetReadDeadline(t time.Time) error
    SetWriteDeadline(t time.Time) error
}

与这个函数相对应的两个函数:

  • func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error)
  • func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error)

分别表示建立TCP请求和IP请求,中间多的laddr 表示本地的地址,一般为nil  。

3.4 func (c *conn) Write(b []byte) (int, error)

conn 连接对象中写入数据,即发送数据给对方,写入的数据是[]byte 类型,成功将返回发送的数据包字节数。

n, err := tcpCoon.Write([]byte("HelloWorld"))
if err != nil{
    fmt.Println(err)
    return
}

3.5 func (c *conn) Read(b []byte) (int, error)

从conn连接对象中读取数据,成功将返回读取到的字节数。

recvData := make([]byte, 2048)
n, err = tcpCoon.Read(recvData)
if err != nil{
   fmt.Println(err)
   return
}
fmt.Println(string(recvData))

3.6 func Listen(net, laddr string) (Listener, error)

Listen函数在服务端使用,让服务端开始监听。

  • net :和上面一样,可以是tcp ip相关的值
  • laddr :要监听的地址,ip+port省略主机地址将使用本机地址127.0.0.1

相应的两个函数:

  • func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error):监听TCP连接
  • func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error):监听IP连接

3.7 func (l *TCPListener) Accept() (Conn, error)

服务端开始监听需要使用Accept 函数来接受客户端连接,此时服务端将进入阻塞状态。

相应的还有一个

  • func (l *TCPListener) AcceptTCP() (*TCPConn, error)
最后修改:2017 年 09 月 12 日
如果觉得我的文章对你有用,请随意赞赏