Master Go Socket and HTTP Programming: Dial, ICMP, and Custom Requests
Learn how to use Go's net package for low‑level socket programming—including TCP, UDP, and ICMP connections with the Dial function—and build HTTP clients with net/http, covering basic requests, POST forms, custom headers, and practical code examples.
Socket Programming with Go
The traditional socket workflow (create, bind, listen/connect, accept, send/receive) is abstracted in Go's standard library. By calling net.Dial you can open a connection for any supported protocol without manually handling the low‑level steps.
Dial Function Signature
func Dial(net, addr string) (Conn, error) netspecifies the protocol name (e.g., "tcp", "udp", "ip4:icmp"), and addr is the host and optional port ("host:port"). If the connection succeeds, a Conn object is returned; otherwise an error is returned.
Typical Dial Usages
TCP: conn, err := net.Dial("tcp", "192.168.0.10:2100") UDP: conn, err := net.Dial("udp", "192.168.0.12:975") ICMP (IPv4): conn, err := net.Dial("ip4:icmp", "www.baidu.com") ICMP (raw): conn, err := net.Dial("ip4:1", "10.0.0.3") Supported network strings include "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6", "ip", "ip4", and "ip6".
Sending and Receiving Data
After establishing a connection, use conn.Write() to send bytes and conn.Read() to receive them.
ICMP Example Program
The following Go program sends an ICMP echo request to a host and validates the identifier and sequence fields in the reply.
package main
import (
"net"
"os"
"bytes"
"fmt"
)
func main() {
if len(os.Args) != 2 {
fmt.Println("Usage:", os.Args[0], "host")
os.Exit(1)
}
service := os.Args[1]
conn, err := net.Dial("ip4:icmp", service)
checkError(err)
var msg [512]byte
msg[0] = 8 // Type: Echo
msg[1] = 0 // Code
// checksum placeholder
msg[4] = 0 // Identifier[0]
msg[5] = 13 // Identifier[1]
msg[6] = 0 // Sequence[0]
msg[7] = 37 // Sequence[1]
length := 8
check := checkSum(msg[0:length])
msg[2] = byte(check >> 8)
msg[3] = byte(check & 0xff)
_, err = conn.Write(msg[0:length])
checkError(err)
_, err = conn.Read(msg[0:])
checkError(err)
fmt.Println("Got response")
if msg[5] == 13 {
fmt.Println("Identifier matches")
}
if msg[7] == 37 {
fmt.Println("Sequence matches")
}
os.Exit(0)
}
func checkSum(msg []byte) uint16 {
sum := 0
for n := 1; n < len(msg)-1; n += 2 {
sum += int(msg[n])*256 + int(msg[n+1])
}
sum = (sum >> 16) + (sum & 0xffff)
sum += sum >> 16
return ^uint16(sum)
}
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
}Running the program (e.g., ./icmptest www.baidu.com) prints:
Got response
Identifier matches
Sequence matchesTCP Example Program (Simple HTTP HEAD)
This example opens a TCP connection to a host, sends an HTTP HEAD request, and prints the response headers.
package main
import (
"net"
"os"
"bytes"
"fmt"
)
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)
_, err = conn.Write([]byte("HEAD / HTTP/1.0
"))
checkError(err)
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
}Executing ./simplehttp qbox.me:80 yields a typical HTTP response header, e.g.,
HTTP/1.1 301 Moved Permanently
Server: nginx/1.0.14
Date: Mon, 21 May 2012 03:15:08 GMT
Content-Type: text/html
Content-Length: 184
Connection: close
Location: https://qbox.me/HTTP Programming with Go's net/http Package
The net/http package provides both client and server implementations. The following sections show how to perform common HTTP operations.
Basic HTTP Client Methods
http.Get(url)– simple GET request. http.Post(url, bodyType, body) – POST with raw body. http.PostForm(url, data) – POST with form‑encoded data. http.Head(url) – retrieve only response headers. client.Do(req) – full control over request, useful for custom headers or cookies.
GET Example
resp, err := http.Get("http://example.com/")
if err != nil {
// handle error
return
}
defer resp.Body.Close()
io.Copy(os.Stdout, resp.Body)POST Example (Uploading an Image)
resp, err := http.Post("http://example.com/upload", "image/jpeg", &imageDataBuf)
if err != nil {
// handle error
return
}
if resp.StatusCode != http.StatusOK {
// handle non‑OK response
return
}POST Form Example
resp, err := http.PostForm("http://example.com/posts", url.Values{
"title": {"article title"},
"content": {"article body"},
})
if err != nil {
// handle error
return
}HEAD Request Example
resp, err := http.Head("http://example.com/")
// resp.Header now contains the header fieldsCustom Request with Do
When more control is needed (e.g., setting a custom User-Agent or adding cookies), construct a http.Request and use an http.Client to execute it.
req, err := http.NewRequest("GET", "http://example.com", nil)
req.Header.Add("User-Agent", "Gobook Custom User-Agent")
client := &http.Client{}
resp, err := client.Do(req)
// process respThese examples demonstrate how Go simplifies both low‑level socket interactions and high‑level HTTP client operations, allowing developers to build networked applications efficiently.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
