Взаимодействие клиента и сервера

Последнее обновление: 18.01.2018

В прошлой теме было рассмотрено создание простейшего сервера TCP, к которому подключается клиент, и этому клиенту отправляется некоторое сообщение. Теперь рассмотрим, как клиент может посылать сообщения и получать ответ.

Для начала определим следующий сервер:

package main
import (
	"fmt"
	"net"
)
var dict = map[string]string{ 
	"red": "красный",
	"green": "зеленый",
	"blue": "синий",
	"yellow": "желтый",
}
	
func main() {
	listener, err := net.Listen("tcp", ":4545") 
	
	if err != nil {
		fmt.Println(err) 
		return 
	} 
	defer listener.Close() 
	fmt.Println("Server is listening...")
	for { 
		conn, err := listener.Accept() 
		if err != nil { 
			fmt.Println(err) 
			conn.Close() 
			continue
		} 
		go handleConnection(conn)  // запускаем горутину для обработки запроса
	} 
}
// обработка подключения
func handleConnection(conn net.Conn) { 
	defer conn.Close()
	for {
		// считываем полученные в запросе данные
		input := make([]byte, (1024 * 4)) 
		n, err := conn.Read(input) 
		if n == 0 || err != nil {
			fmt.Println("Read error:", err)
			break
		}	 
		source := string(input[0:n])
		// на основании полученных данных получаем из словаря перевод 
		target, ok := dict[source]
		if ok == false{				// если данные не найдены в словаре
			target = "undefined"
		}
		// выводим на консоль сервера диагностическую информацию
		fmt.Println(source, "-", target)
		// отправляем данные клиенту
		conn.Write([]byte(target))
	}
}

Сервер имитирует поведение программы для перевода слов. Для этого определен словарь dit, который содержит англоязычные слова и их перевод.

В бесконечном цикле сервер принимает подключения. Однако вместо прямой обработки подключения сервер запускает горутину в виде функции handleConnection, в которой и обрабатывается подключение. Это позволит входящим клиентам не ждать, пока первый из них будет обработан. Таким образом, все входящие клиенты в определенной степени будут обрабатываться одновременно.

В функции handleConnection получаем запрос от клиента. Для этого выделяем буфер достаточной длины в 4096 байт.

input := make([]byte, (1024 * 4)) 
n, err := conn.Read(input) 

В данном случае мы ожидаем, что запрос от клиента не превысит 4096 байт, однако точный размер запроса и его максимальный размер не всегда бывают известны. В этом случае мы можем применять различные техники, в частности, в бесконечном цикле считывать данные запроса от клиента и только потом их обрабатывать. Но в данном случае мы разберем более простую ситуацию.

Получив запрос, преобразовав его строку, получаем значение из словаря и отправляем его обратно клиенту:

conn.Write([]byte(target))

Для взаимодействия с этми сервером определим следующий клиент:

package main
import (
	"fmt"
	"net"
)
func main() {

	conn, err := net.Dial("tcp", "127.0.0.1:4545") 
	if err != nil { 
		fmt.Println(err) 
		return 
	}
	defer conn.Close()
	for{
		var source string
		fmt.Print("Введите слово: ") 
		_, err := fmt.Scanln(&source) 
		if err != nil { 
			fmt.Println("Некорректный ввод", err) 
			continue
		}
		// отправляем сообщение серверу
		if n, err := conn.Write([]byte(source));
		n == 0 || err != nil { 
			fmt.Println(err) 
			return 
		}
		// получем ответ
		fmt.Print("Перевод:")
		buff := make([]byte, 1024)
		n, err := conn.Read(buff)
		if err !=nil{ break}
		fmt.Print(string(buff[0:n]))
		fmt.Println()
	}
}

На клиенте в бесконечном цикле вводим слово для перевода и отправляем серверу сообщение:

if n, err := conn.Write([]byte(source));

И затем получаем от сервера ответ и выводим его на консоль. Так как ответ от сервера может быть переменной длины, то для получения ответа в бесконечом цикле считываем данные с помощью метода Read:

buff := make([]byte, 1024)
n, err := conn.Read(buff)
if err !=nil{ break}
fmt.Print(string(buff[0:n]))

Запустим сервер.

Отправка данных из клиента на сервер TCP в языке Go

Затем запустим программу клиента и введем какое-либо значение и сервер возвратит перевод слова:

Отправка данных из клиента на сервер в Golang

Для выхода из программ сервера и клиента необходимо нажать комбинацию клавиш Ctrl+C.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850