Следите за новинками
в нашем Telegram канале. Жми, чтобы подписаться:)
⊗goSpSoEx 252 of 280 menu
◀ ▶

Обмен по TCP в Go

После установки TCP-связи обмен идет в обе стороны по одному каналу. Сервер может сначала дождаться байтов от клиента, разобрать их как текст и записать ответ в тот же объект соединения, не открывая новый порт.

Чтение не обязано заполнить весь буфер: за один вызов приходит столько байтов, сколько клиент уже успел отправить. Ответ собирают из литерала и прочитанного куска; длину при записи и печати берут из числа, которое вернул прием.

Клиент шлет строку, сервер отвечает префиксом "echo: " и тем же текстом:

package main import ( "fmt" "log" "net" "time" ) func replyServer(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) } text := string(buf[:n]) out := "echo: " + text _, err = conn.Write([]byte(out)) if err != nil { log.Fatal(err) } } func main() { addr := "127.0.0.1:9090" go replyServer(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("ping")) if err != nil { log.Fatal(err) } buf := make([]byte, 256) n, err := conn.Read(buf) if err != nil { log.Fatal(err) } fmt.Println(string(buf[:n])) }

На экране клиента "echo: ping". Сервер прочитал три байта, собрал ответ и отправил его до закрытия соединения.

Если клиент шлет более длинную фразу, тот же порядок шагов сохраняется:

package main import ( "fmt" "log" "net" "time" ) func replyServer(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) } out := "echo: " + string(buf[:n]) _, err = conn.Write([]byte(out)) if err != nil { log.Fatal(err) } } func main() { addr := "127.0.0.1:9090" go replyServer(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("long message")) if err != nil { log.Fatal(err) } buf := make([]byte, 256) n, err := conn.Read(buf) if err != nil { log.Fatal(err) } fmt.Println(string(buf[:n])) }

Дано сообщение клиента:

clientLine := "ask"

На сервере после чтения в буфер 256 байт отправьте клиенту строку "reply: ask", если в буфер попало ровно clientLine.

Дан адрес:

addr := "127.0.0.1:9090"

Клиент отправляет "go" на addr и ждет ответ; сервер возвращает "echo: go". Опишите порядок вызовов чтения и записи на стороне сервера.

Скажите, почему ответ пишут в conn, а не в ln, после того как клиент уже подключился.

← →
↑
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить