最新消息:

Go语言Socket编程

go admin 3113浏览 0评论

大部分底层网络的编程都离不开socket编程。HTTP编程、Web开发、IM通信、视频流传输的底层都是socket编程。关于socket编程的基础知识参考TCP/IP协议栈的相关知识。

socket源于Unix,C语言世界中的socket编程。Python采用C语言实现,其自带的socket接口可以看作是Unix socket的OOP风格的socket编程接口。大致的过程如下:

服务器端:

  1. 创建套接字
  2. 绑定地址
  3. 设置监听队列
  4. 监听请求
  5. 处理请求
  6. 关闭套接字

客户端:

  1. 创建套接字
  2. 连接服务器
  3. 发送数据
  4. 接收数据
  5. 关闭套接字

但Go语言采用一套新的接口,该接口比Unix中的socket简介多。由于Golang的静态编译,使用Golang编写的socket网络工具使用起来很方便。

本文先从TCP socket编程开始,然后到UDP socket,最后以一个简单的socket工具作为结尾。

TCP Socket

Golang net包中TCPConn用来建立TCP客户端、TCP服务器端间的通信通道。类似于Python中的socket对象(通过socket.socket创建)通过DialTCP函数创建该对象。TCPListener服务器端socket,监听网络请求,通过ListenTCP函数创建该对象。形象地理解,可以把TCPConn看作是TCP的连接器;TCPListener看作是TCP监听器。监听器等待客户端连接,一旦有连接进来,创建TCP连接器,然后通过TCP连接器进行服务器端和客户端的通信。

下面通过TCP心跳(返回服务器端时间)来举例,编程中还有一些细节问题,这里不详细说,看代码注释。

TCP Server

TCP服务器端通过ListenTCP创建TCPListener对象。调用Accept方法进入LISTEN状态(参考TCP状态机)

编写tcp_tick_time.go代码。

package main
import (
    "fmt"
    "log"
    "net"
    "os"
    "time"
)
func echo(conn *net.TCPConn) {
    tick := time.Tick(5 * time.Second) // 五秒的心跳间隔
    for now := range tick {
        n, err := conn.Write([]byte(now.String()))
        if err != nil {
            log.Println(err)
            conn.Close()
            return
        }
        fmt.Printf("send %d bytes to %s\n", n, conn.RemoteAddr())
    }
}
func main() {
    address := net.TCPAddr{
        IP:   net.ParseIP("127.0.0.1"), // 把字符串IP地址转换为net.IP类型
        Port: 8000,
    }
    listener, err := net.ListenTCP("tcp4", &address) // 创建TCP4服务器端监听器
    if err != nil {
        log.Fatal(err) // Println + os.Exit(1)
    }
    for {
        conn, err := listener.AcceptTCP()
        if err != nil {
            log.Fatal(err) // 错误直接退出
        }
        fmt.Println("remote address:", conn.RemoteAddr())
        go echo(conn)
    }
}

通过终端直接启动。

go run tcp_tick_time.go

通过简单的客户端连接,我们可以看到该程序终端的显示信息:

remote address: 127.0.0.1:1915
send 37 bytes to 127.0.0.1:1915
send 37 bytes to 127.0.0.1:1915
send 37 bytes to 127.0.0.1:1915
send 35 bytes to 127.0.0.1:1915
send 37 bytes to 127.0.0.1:1915
send 37 bytes to 127.0.0.1:1915
send 37 bytes to 127.0.0.1:1915
2017/08/29 9:23:49 write tcp4 127.0.0.1:8000->127.0.0.1:1915: wsasend: An established connection was aborted by the software in your host machine.
send 0 bytes to 127.0.0.1:1915

TCP Client

通过func DialTCP(net string, laddr, raddr TCPAddr) (TCPConn, error)创建TCP客户端。net需要指定具体的TCP
网络类型:”tcp”, “tcp4”, “tcp6”。laddr表示本地地址,一般为nil。raddr为要连接的服务器地址。

我们写一个简单的HTTP客户端。

package main 
import (
    "net"
    "log"
    "fmt"
    "io/ioutil"
    "os"
)
func main() {
    if len(os.Args) != 2 {
    log.Fatalf("Usage: %s host:port", os.Args[0])
    }
    service := os.Args[1]
    tcpAddr, err := net.ResolveTCPAddr("tcp4", service)
    if err != nil {
        log.Fatal(err)
    }
    conn, err := net.DialTCP("tcp4", nil, tcpAddr)
    if err != nil {
        log.Fatal(err)
    }
    n, err := conn.Write([]byte("HEAD / HTTP/1.1\r\n\r\n"))
    if err != nil {
        log.Fatal(err)
    }

完。

转载请注明:爱开源 » Go语言Socket编程

您必须 登录 才能发表评论!