Go Socket programming (1): Dial function and its use

Traditional Socket programming

When network programming in Go language, it is more concise than traditional network programming.

Recall that when we write a network program in C language, taking the network service based on the TCP protocol as an example, the implementation process of the client and server is usually like this:

Socket programming icon

From the point of view of the server, code writing is divided into the following steps:

  1. Establish and bind Socket: First, the server uses a  socket() function to establish a network socket, and then uses the  bind() function to bind the specified IP and port for the socket;
  2. Monitor request: Next, the server uses a  listen() function to monitor the client's request to bind the IP and port;
  3. Receiving connection: If there is a request, and the connection is successfully established through the three-way handshake, use the  accept() function to receive and process the connection;
  4. Processing request and sending response: The server  read() reads the request data sent by the client from the above-mentioned established connection through the write() function , and then sends the response data to the client through the function after processing  .

From the client point of view, code writing is divided into the following steps:

  1. Socket establishment: the client also uses  socket()functions to establish a network socket;
  2. Establish a connection: then call the  connect() function to pass in the IP and port number to establish a connection with the designated server network program;
  3. Send request and receive response: After the connection is established successfully, the client can write() send data to the server through the  function, and use the  read() function to receive the response from the server.

The general process of network services based on UDP protocol is also the same, but there is no need to establish a connection between the server and the client.

The Go language standard library abstracts and encapsulates this process. No matter what protocol or form of connection we use, we only need to call the net.Dial() function, which greatly simplifies the amount of code writing. Let's take a look at the function below. Usage.

Dial() function

Dial() The prototype of the function is as follows:

func Dial(network, address string) (Conn, error) {
    var d Dialer
    return d.Dial(network, address)
}

The  network parameter indicates the incoming network protocol (such as  tcp, udp etc.), the address parameter indicates the incoming IP address or domain name, and the port number is optional. If you need to specify it, follow the address or domain name in the form of ":" Enough. If the connection is successful, the function returns the connection object, otherwise it returns  error.

Let's take a look at the calling methods of several common protocols.

1. TCP connection:

conn, err := net.Dial("tcp", "192.168.10.10:80")

2. UDP connection:

conn, err := net.Dial("udp", "192.168.10.10:8888")

3. ICMP connection (using protocol name):

conn, err := net.Dial("ip4:icmp", "www.xueyuanjun.com")

Note: It ip4 means IPv4, and the corresponding  ip6 means IPv6.

4. ICMP connection (using protocol number):

conn, err := net.Dial("ip4:1", "10.0.0.3")

Note: We can check the meaning of protocol numbers through the following link: http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml .

At present, the Dial() function supports the following network tcpprotocols: tcp4, tcp6, udp, udp4, udp6, ip, ip4, ip6, unix, , unixgram and  unixpacketthese agreements are explained as follows:

  • tcp: Represents the TCP protocol, and the version of the IP protocol it is based on address adapts to the value of the parameter  .
  • tcp4: Represents the TCP protocol based on the fourth version of the IP protocol.
  • tcp6: Represents the TCP protocol based on the sixth edition of the IP protocol.
  • udp: Represents the UDP protocol, and the version of the IP protocol it is based on address adapts to the value of the parameter  .
  • udp4: Represents the UDP protocol based on the fourth version of the IP protocol.
  • udp6: Represents the UDP protocol based on the sixth edition of the IP protocol.
  • unix: An internal socket communications protocol in representing Unix domain to  SOCK_STREAM as socket type.
  • unixgram: An internal socket communications protocol in representing Unix domain to  SOCK_DGRAM as socket type.
  • unixpacket: An internal socket communications protocol in representing Unix domain to  SOCK_SEQPACKET as socket type.

After successfully establishing a connection, we can send and receive data. When sending data, use conn the Write() method of the connection object and use  the  method when receiving data  Read() . Next, I will show you the realization of network programming in Go language through a simple sample program.

TCP sample program 

We will implement a simple HTTP protocol by establishing a TCP connection-by sending an HTTP Head request to the network host, and reading the information returned by the network host, the specific code implementation is as follows: 

package main

import (
    "bytes"
    "fmt"
    "io"
    "net"
    "os"
)

func main() {
    if len(os.Args) != 2 {
        fmt.Fprintf(os.Stderr, "Usage: %s host:port", os.Args[0])
        os.Exit(1)
    }
    // 从参数中读取主机信息
    service := os.Args[1]

    // 建立网络连接
    conn, err := net.Dial("tcp", service)
    // 连接出错则打印错误消息并退出程序
    checkError(err)

    // 调用返回的连接对象提供的 Write 方法发送请求
    _, err = conn.Write([]byte("HEAD / HTTP/1.0\r\n\r\n"))
    checkError(err)

    // 通过连接对象提供的 Read 方法读取所有响应数据
    result, err := readFully(conn)
    checkError(err)

    // 打印响应数据
    fmt.Println(string(result))

    os.Exit(0)
}

func checkError(err error) {
    if err != nil {
        fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
        os.Exit(1)
    }
}

func readFully(conn net.Conn) ([]byte, error) {
    // 读取所有响应数据后主动关闭连接
    defer conn.Close()

    result := bytes.NewBuffer(nil)
    var buf [512]byte
    for {
        n, err := conn.Read(buf[0:])
        result.Write(buf[0:n])
        if err != nil {
            if err == io.EOF {
                break
            }
            return nil, err
        }
    }
    return result.Bytes(), nil
}

Test the above code, the output is as follows:

Go language TCP programming code example

For  80 ports, you can also  http substitute:

Go language TCP programming code example

It can be seen that the overall implementation code of the network program written in the Go language is very simple and clear, that is, establishing a connection, sending data, and receiving data, without us needing to pay attention to the details of the communication of the different underlying protocols.

Guess you like

Origin blog.csdn.net/wxy_csdn_world/article/details/107445135