TCP-сервер в Go
Сервер не инициирует связь сам: он объявляет, что готов принимать TCP на заданном адресе, и ждет первого клиента. Объект слушателя держит порт открытым; когда клиент подключится, отдельный объект соединения представляет уже установленный канал с этим клиентом.
После успешного принятия работают с соединением так же, как на клиенте: читают и пишут байты, закрывают канал при завершении. Слушатель закрывают отложенным вызовом, когда серверу больше не нужен порт, иначе процесс может долго держать ресурс.
Один клиент и простая печать прочитанного куска:
package main
import (
"fmt"
"log"
"net"
"time"
)
func serveOnce(addr string) {
ln, err := net.Listen("tcp", addr)
if err != nil {
log.Fatal(err)
}
defer ln.Close()
conn, err := ln.Accept()
if err != nil {
log.Fatal(err)
}
defer conn.Close()
buf := make([]byte, 256)
n, err := conn.Read(buf)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(buf[:n]))
}
func main() {
addr := "127.0.0.1:9090"
go serveOnce(addr)
time.Sleep(10 * time.Millisecond)
conn, err := net.Dial("tcp", addr)
if err != nil {
log.Fatal(err)
}
defer conn.Close()
_, err = conn.Write([]byte("server test"))
if err != nil {
log.Fatal(err)
}
time.Sleep(50 * time.Millisecond)
}
На экране сервера "server test".
Клиент в main нужен только чтобы
отправить строку; в следующих уроках
ответ пойдет обратно в то же соединение.
Тот же серверный каркас без клиента в том же файле, если проверку делаете вручную второй программой:
package main
import (
"fmt"
"log"
"net"
)
func main() {
addr := "127.0.0.1:9090"
ln, err := net.Listen("tcp", addr)
if err != nil {
log.Fatal(err)
}
defer ln.Close()
conn, err := ln.Accept()
if err != nil {
log.Fatal(err)
}
defer conn.Close()
buf := make([]byte, 256)
n, err := conn.Read(buf)
if err != nil {
log.Fatal(err)
}
fmt.Println("got", string(buf[:n]))
}
Дан адрес:
addr := "127.0.0.1:9090"
Привяжите слушатель к addr по
протоколу TCP, примите одно соединение
и закройте слушатель отложенным вызовом.
Дан фрагмент после успешного принятия:
conn, err := ln.Accept()
if err != nil {
log.Fatal(err)
}
Допишите отложенное закрытие conn
и чтение в буфер 256 байт.
Скажите, чем объект слушателя отличается от объекта соединения после принятия клиента.