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:
From the point of view of the server, code writing is divided into the following steps:
- Establish and bind Socket: First, the server uses a
socket()
function to establish a network socket, and then uses thebind()
function to bind the specified IP and port for the socket; - Monitor request: Next, the server uses a
listen()
function to monitor the client's request to bind the IP and port; - 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; - Processing request and sending response: The server
read()
reads the request data sent by the client from the above-mentioned established connection through thewrite()
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:
- Socket establishment: the client also uses
socket()
functions to establish a network socket; - 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; - 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 theread()
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 tcp
protocols: tcp4
, tcp6
, udp
, udp4
, udp6
, ip
, ip4
, ip6
, unix
, , unixgram
and unixpacket
these agreements are explained as follows:
tcp
: Represents the TCP protocol, and the version of the IP protocol it is based onaddress
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 onaddress
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 toSOCK_STREAM
as socket type.unixgram
: An internal socket communications protocol in representing Unix domain toSOCK_DGRAM
as socket type.unixpacket
: An internal socket communications protocol in representing Unix domain toSOCK_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:
For 80
ports, you can also http
substitute:
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.