Create a TCP and UDP Client and Server using Go
Traducciones al EspañolEstamos traduciendo nuestros guías y tutoriales al Español. Es posible que usted esté viendo una traducción generada automáticamente. Estamos trabajando con traductores profesionales para verificar las traducciones de nuestro sitio web. Este proyecto es un trabajo en curso.
Go is a compiled, statically typed programming language developed by Google. Many modern applications, including Docker, Kubernetes, and Terraform, are written in Go. Go packages allow developers to organize and reuse Go code in a simple and maintainable manner.
In this guide, you will use the net package, which is a part of Go’s standard library, to create TCP and UDP servers and clients. This guide is meant to provide instructional examples to help you become more familiar with the Go programming language.
Scope of this Guide
Throughout this guide you will create the following:
- A TCP server and client. The TCP server accepts incoming messages from a TCP client and responds with the current date and time.
- A UDP server and client. The UDP server accepts incoming messages from a UDP client and responds with a random number.
- A concurrent TCP server that accepts incoming messages from several TCP clients and responds with the number of clients currently connected to it.
Before You Begin
- If you are not familiar with using Go packages, review the Getting Started with Go Packages guide. 
- Install Go on your computer if it is not already installed. You can follow our guide How to Install Go on Ubuntu for installation steps. - This guide requires Go version 1.8 or higher. It is considered good practice to have the latest version of Go installed. You can check your Go version by executing the following command: - go version
sudo. If you are not familiar with the sudo command, see the
Users and Groups guide.Protocol Definitions
| Protocol | Definition | 
|---|---|
| TCP (Transmission Control Protocol) | TCP’s principal characteristic is that it is a reliable protocol by design. If there is no proof of a packet’s delivery, TCP will resend the packet. Some of the tasks TCP packets can be used for are establishing connections, transferring data, sending acknowledgements, and closing connections. | 
| IP (Internet Protocol) | The IP protocol adheres to the end-to-end principle, which places all network intelligence in the end nodes and not in the intermediary nodes. This design favors a reduction in network complexity over reliability. For this reason, the Internet Protocol does not guarantee a reliable delivery of packets over a network. Instead, IP works together with TCP to reliably deliver packets over a network. | 
| UDP (User Datagram Protocol): | UDP provides a simpler implementation of the transport layer protocol that, while less reliable than TCP, is much faster. UDP does not provide error checking, correction or packet retransmission, which makes it very fast. When speed is more important than reliability, UDP is generally chosen over TCP. UDP is commonly used for online gaming, video chatting, and other real-time applications. | 
The net Package
Go’s net package provides a portable interface for network I/O, including TCP/IP, UDP, domain name resolution, and Unix domain sockets. You will use this package to create TCP and UDP servers and clients in this guide.
net Package Functions
Use the table below as a quick reference for some of the net package functions used throughout this guide. To view all types and functions included in the net package, see Golang’s official documentation.
| Type | Function | 
|---|---|
| type Listener | func Listen(network, address string) (Listener, error)• Thenetworkparameter defines the type of network to use and accepts valuestcp,tcp4(IPv4-only),tcp6(IPv6-only),unix(Unix sockets), orunixpacket.   • Theaddressparameter defines the server address and port number that the server will listen on. | 
| type UDPConn | func ListenUDP(network string, laddr *UDPAddr) (*UDPConn, error)• Used to create UDP servers.   • Thenetworkparameter must be a UDP network name.   • Theladdrparameter defines the server address and port number that the server will listen on.func DialUDP(network string, laddr, raddr *UDPAddr) (*UDPConn, error)• Used to specify the kind of client you will create.   • Thenetworkparameter must be a UDP network name.   • Theladdris the listening address (server). Ifladdris nil, a local address is automatically chosen.   •raddris the response address (client). If the IP field ofraddris nil or an unspecified IP address, the local system is assumed. | 
| type UDPAddr | func ResolveUDPAddr(network, address string) (*UDPAddr, error)• This function returns the address of a UDP end point.   • Thenetworkparameter must be a UDP network name.   • Theaddressparameter has the formhost:port. The host must be a an IP address, or a host name that can be resolved to IP addresses. | 
| type TCPAddr | func ResolveTCPAddr(network, address string) (*TCPAddr, error)• This function returns the address of a TCP end point.   • Thenetworkparameter must be a TCP network name.   • Theaddressparameter has the formhost:port. The host must be a an IP address, or a host name that can be resolved to IP addresses. | 
| type Conn | func Dial(network, address string) (Conn, error)• This function connects to the address on the named network.   • Thenetworkparameter can betcp,tcp4(IPv4-only),tcp6(IPv6-only),udp,udp4(IPv4-only),udp6(IPv6-only),ip,ip4(IPv4-only),ip6(IPv6-only),unix,unixgramandunixpacket.   • When using TCP or UDP networks, theaddressparameter has the formhost:port. The host must be a an IP address, or a host name that can be resolved to IP addresses. | 
| type TCPConn | func DialTCP(network string, laddr, raddr *TCPAddr) (*TCPConn, error)• This function connects to the address on the TCP networks.   • Thenetworkparameter must be a TCP network name.   • Theladdris the listening address (server). Ifladdris nil, a local address is automatically chosen.   •raddris the response address (client). If the IP field ofraddris nil or an unspecified IP address, the local system is assumed. | 
Create a TCP Client and Server
In this section, you will create a generic TCP client and server using Go. After creating the client and server, you will run them to test their connection with each other.
Create the TCP Client
The TCP client that you will create in this section will allow you to interact with any TCP server.
- In your current working directory, create a file named - tcpC.gowith the following content:- File: ./tcpC.go
- 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39- package main import ( "bufio" "fmt" "net" "os" "strings" ) func main() { arguments := os.Args if len(arguments) == 1 { fmt.Println("Please provide host:port.") return } CONNECT := arguments[1] c, err := net.Dial("tcp", CONNECT) if err != nil { fmt.Println(err) return } for { reader := bufio.NewReader(os.Stdin) fmt.Print(">> ") text, _ := reader.ReadString('\n') fmt.Fprintf(c, text+"\n") message, _ := bufio.NewReader(c).ReadString('\n') fmt.Print("->: " + message) if strings.TrimSpace(string(text)) == "STOP" { fmt.Println("TCP client exiting...") return } } }
 
- This file creates the mainpackage, which declares themain()function. The function will use the imported packages to create a TCP client.
- The main()function gathers command line arguments in theargumentsvariable and makes sure that a value forhost:portwas sent.
- The CONNECTvariable stores the value ofarguments[1]to be used in thenet.Dial()call.
- A call to net.Dial()begins the implementation of the TCP client and will connect you to the desired TCP server. The second parameter ofnet.Dial()has two parts; the first is the hostname or the IP address of the TCP server and the second is the port number the TCP server listens on.
- bufio.NewReader(os.Stdin)and- ReadString()is used to read user input. Any user input is sent to the TCP server over the network using- Fprintf().
- bufioreader and the- bufio.NewReader(c).ReadString('\n')statement read the TCP server’s response. The- errorvariable is ignored here for simplicity.
- The entire forloop that is used to read user input will only terminate when you send theSTOPcommand to the TCP server.
Create the TCP Server
You are now ready to create the TCP server. The TCP server will return the current date and time to the TCP client using a single network packet.
- In your current working directory, create a file named - tcpS.gowith the following content:- File: ./tcpS.go
- 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50- package main import ( "bufio" "fmt" "net" "os" "strings" "time" ) func main() { arguments := os.Args if len(arguments) == 1 { fmt.Println("Please provide port number") return } PORT := ":" + arguments[1] l, err := net.Listen("tcp", PORT) if err != nil { fmt.Println(err) return } defer l.Close() c, err := l.Accept() if err != nil { fmt.Println(err) return } for { netData, err := bufio.NewReader(c).ReadString('\n') if err != nil { fmt.Println(err) return } if strings.TrimSpace(string(netData)) == "STOP" { fmt.Println("Exiting TCP server!") return } fmt.Print("-> ", string(netData)) t := time.Now() myTime := t.Format(time.RFC3339) + "\n" c.Write([]byte(myTime)) } }
 
- This file creates the mainpackage, which declares themain()function. The function will use the imported packages to create a TCP server.
- The main()function gathers command line arguments in theargumentsvariable and includes error handling.
- The net.Listen()function makes the program a TCP server. This functions returns aListenervariable, which is a generic network listener for stream-oriented protocols.
- It is only after a successful call to Accept()that the TCP server can begin to interact with TCP clients.
- The current implementation of the TCP server can only serve the first TCP client that connects to it, because the Accept()call is outside of theforloop. In the Create a Concurrent TCP Server section of this guide, you will see a TCP server implementation that can serve multiple TCP clients using Goroutines.
- The TCP server uses regular File I/O functions to interact with TCP clients. This interaction takes place inside the forloop. Similarly to the TCP client, when the TCP server receives theSTOPcommand from the TCP client, it will terminate.
Test the TCP Client and Server
You can now test your TCP client and server. You will need to execute the TCP server first so that the TCP client has somewhere it can connect to.
- Run your TCP server. From the directory containing the - tcpS.gofile, run the following command:- go run tcpS.go 1234- The server will listen on port number - 1234. You will not see any output as a result of this command.
- Open a second shell session to execute the TCP client and to interact with the TCP server. Run the following command: - go run tcpC.go 127.0.0.1:1234- Note - If the TCP server is not running on the expected TCP port, you will get the following error message from - tcpC.go:- dial tcp [::1]:1234: connect: connection refused
- You will see a - >>prompt waiting for you to enter some text. Type in- Hello!to receive a response from the TCP server:- Hello!- You should see a similar output: - >> Hello! ->: 2019-05-23T19:43:21+03:00
- Send the - STOPcommand to exit the TCP client and server:- STOP- You should see a similar output in the client: - >> STOP ->: TCP client exiting...- The output on the TCP server side will resemble the following: - -> Hello! Exiting TCP server!
Create a UDP Client and Server
In this section, you will create a UDP client and server. After creating the client and server, you will run them both to test their connection with each other. A UDP client can be generic and can communicate with multiple UDP servers. On the other hand, a UDP server cannot be completely generic, because it typically implements a specific functionality. In the case of our UDP server example, it will return random numbers to UDP clients that connect to it.
Create the UDP Client
The UDP client that you will create in this section will allow you to interact with any UDP server.
- In your current working directory, create a file named - udpC.gowith the following content:- File: ./udpC.go
- 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54- package main import ( "bufio" "fmt" "net" "os" "strings" ) func main() { arguments := os.Args if len(arguments) == 1 { fmt.Println("Please provide a host:port string") return } CONNECT := arguments[1] s, err := net.ResolveUDPAddr("udp4", CONNECT) c, err := net.DialUDP("udp4", nil, s) if err != nil { fmt.Println(err) return } fmt.Printf("The UDP server is %s\n", c.RemoteAddr().String()) defer c.Close() for { reader := bufio.NewReader(os.Stdin) fmt.Print(">> ") text, _ := reader.ReadString('\n') data := []byte(text + "\n") _, err = c.Write(data) if strings.TrimSpace(string(data)) == "STOP" { fmt.Println("Exiting UDP client!") return } if err != nil { fmt.Println(err) return } buffer := make([]byte, 1024) n, _, err := c.ReadFromUDP(buffer) if err != nil { fmt.Println(err) return } fmt.Printf("Reply: %s\n", string(buffer[0:n])) } }
 - This file creates the mainpackage, which declares themain()function. The function will use the imported packages to create a UDP client.
- The main()function gathers command line arguments in theargumentsvariable and includes error handling.
- Regular File I/O functions are used by the UDP client to interact with the UDP server. The client will terminate when you send the STOPcommand to the UDP server. This is not part of the UDP protocol, but is used in the example to provide the client with a way to exit.
- A UDP end point address is returned by the net.ResolveUDPAddr()function. The UDP end point is of typeUDPAddrand contains IP and port information.
- The connection to the UDP server is established with the use of the net.DialUDP()function.
- bufio.NewReader(os.Stdin)and- ReadString()is used to read user input.
- The ReadFromUDP()function reads a packet from the server connection and will return if it encounters an error.
 
Create the UDP Server
You are now ready to create the UDP server. You will write the UDP server code to respond to any connected client with random numbers.
- In your current working directory, create a file named - udps.gowith the following content:- File: ./udpS.go
- 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59- package main import ( "fmt" "math/rand" "net" "os" "strconv" "strings" "time" ) func random(min, max int) int { return rand.Intn(max-min) + min } func main() { arguments := os.Args if len(arguments) == 1 { fmt.Println("Please provide a port number!") return } PORT := ":" + arguments[1] s, err := net.ResolveUDPAddr("udp4", PORT) if err != nil { fmt.Println(err) return } connection, err := net.ListenUDP("udp4", s) if err != nil { fmt.Println(err) return } defer connection.Close() buffer := make([]byte, 1024) rand.Seed(time.Now().Unix()) for { n, addr, err := connection.ReadFromUDP(buffer) fmt.Print("-> ", string(buffer[0:n-1])) if strings.TrimSpace(string(buffer[0:n])) == "STOP" { fmt.Println("Exiting UDP server!") return } data := []byte(strconv.Itoa(random(1, 1001))) fmt.Printf("data: %s\n", string(data)) _, err = connection.WriteToUDP(data, addr) if err != nil { fmt.Println(err) return } } }
 - This file creates the mainpackage, which declares themain()function. The function will use the imported packages to create a UDP server.
- The main()function gathers command line arguments in theargumentsvariable and includes error handling.
- The net.ListenUDP()function tells the application to listen for incoming UDP connections, which are served inside theforloop. This is the function call that makes the program a UDP server.
- The ReadFromUDP()andWriteToUDP()functions are used to read data from a UDP connection and write data to a UDP connection, respectively. A byte slice is stored in thedatavariable and used to write the desired data. Thebuffervariable also stores a byte slice and is used to read data.
- Since UDP is a stateless protocol, each UDP client is served and then the connection closes automatically. The UDP server program will only exit when it receives the STOPkeyword from a UDP client. Otherwise, the server program will continue to wait for more UDP connections from other clients.
 
Test the UDP Client and Server
You can now test your UDP client and server. You will need to execute the UDP server first so that the UDP client has somewhere it can connect to.
- Run your UDP server. From the directory containing the - udpS.gofile, run the following command:- go run udpS.go 1234- The server will listen on port number - 1234. You will not see any output as a result of this command.
- Open a second shell session to execute the UDP client and to interact with the UDP server. Run the following command: - go run udpC.go 127.0.0.1:1234
- You will see a - >>prompt waiting for you to enter some text. Type in- Hello!to receive a response from the UDP server:- Hello!- You should see a similar output: - The UDP server is 127.0.0.1:1234 >> Hello! Reply: 82
- Send the - STOPcommand to exit the UDP client and server:- You should see a similar output on the client side: - >> STOP Exiting UDP client!- The output on the UDP server side will be as follows: - -> STOP Exiting UDP server!
Create a Concurrent TCP Server
This section demonstrates the implementation of a concurrent TCP server. The benefit of a concurrent TCP server is that it can serve multiple clients. In Go, this is accomplished by creating a separate Goroutine to serve each TCP client.
The example TCP server keeps a running count of the number of TCP clients it has served so far. The counter increases by one each time a new TCP client connects to the TCP server. The current value of that counter is returned to each TCP client.
- In your current working directory, create a file named - concTCP.gowith the following content:- File: ./concTCP.go
- 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59- package main import ( "bufio" "fmt" "net" "os" "strconv" "strings" ) var count = 0 func handleConnection(c net.Conn) { fmt.Print(".") for { netData, err := bufio.NewReader(c).ReadString('\n') if err != nil { fmt.Println(err) return } temp := strings.TrimSpace(string(netData)) if temp == "STOP" { break } fmt.Println(temp) counter := strconv.Itoa(count) + "\n" c.Write([]byte(string(counter))) } c.Close() } func main() { arguments := os.Args if len(arguments) == 1 { fmt.Println("Please provide a port number!") return } PORT := ":" + arguments[1] l, err := net.Listen("tcp4", PORT) if err != nil { fmt.Println(err) return } defer l.Close() for { c, err := l.Accept() if err != nil { fmt.Println(err) return } go handleConnection(c) count++ } }
 - This file creates the main package, which declares the handleConnection()andmain()functions.
- The main()function will use the imported packages to create a concurrent TCP server. It gathers command line arguments in theargumentsvariable and includes error handling.
- Each TCP client is served by a separate Goroutine that executes the handleConnection()function. This means that while a TCP client is served, the TCP server is free to interact with more TCP clients. TCP clients are connected using theAccept()function.
- Although the Accept()function can be executed multiple times, thenet.Listen()function needs to be executed only once. For this reason thenet.Listen()function remains outside of theforloop.
- The forloop in themain()function is endless because TCP/IP servers usually run nonstop. However, if thehandleConnection()function receives theSTOPmessage, the Goroutine that runs it will exit and the related TCP connection will close.
 
Test the Concurrent TCP Server
In this section, you will test the concurrent TCP server using the netcat command line utility.
- Run your concurrent TCP server. From the directory containing the - concTCP.gofile, run the following command:- go run concTCP.go 1234- The command creates a TCP server that listens on port number - 1234. You can use any port number, however, ensure it is not already in use and that you have the required privileges. Reference the list of well-known TCP and UDP ports, if needed.
- Use netcat to establish a connection with the TCP server. By default, netcat will establish a TCP connection with a remote host on the specified port number. - nc 127.0.0.1 1234
- After issuing the previous command, you will not see any change in your output. Type - Hello!to send a packet to the TCP server:- Hello!- The TCP server will return the number of current client connections as its response. Since this is your first connection established with the TCP server, you should expect an output of - 1.- Hello! 1- If you’d like, you can open a new shell session and use netcat to establish a second connection with the TCP server by repeating Step 2. When you send the server a second - Hello!, you should receive a response of- 2this time.
- You can also connect to the TCP server using the TCP client you created in the Create the TCP Client section of the guide. Ensure you are in the directory containing the - tcpC.gofile and issue the following command:- go run tcpC.go 127.0.0.1:1234
- You will see a - >>prompt waiting for you to enter some text. Type in- Hello!to receive a response from the TCP server:- Hello!- You should see a similar output indicating - 3client connections:- >> Hello! ->: 3
- Send the - STOPcommand to exit the TCP client:- You should see a similar output on the client: - >> STOP ->: TCP client exiting...- The output on the TCP server side will be as follows: - .Hello! .Hello! .Hello!- Note From the shell session running the TCP server, type CTRL-c to interrupt program execution and then, CTRL-D to close all client connections and to stop the TCP server.
More Information
You may wish to consult the following resources for additional information on this topic. While these are provided in the hope that they will be useful, please note that we cannot vouch for the accuracy or timeliness of externally hosted materials.
This page was originally published on