← Назад к вопросам

Приведи примеры использования TCP

1.0 Junior🔥 141 комментариев
#Сетевые протоколы и API

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Примеры использования TCP в Go

Что такое TCP?

TCP (Transmission Control Protocol) — это протокол надёжной доставки данных по сети. В отличие от UDP, TCP гарантирует:

  • Доставку всех пакетов
  • Порядок передачи данных
  • Отсутствие дублей

Транспортный уровень OSI.

Пример 1: TCP Сервер

package main

import (
    "fmt"
    "log"
    "net"
)

func main() {
    // Слушаем на порту 8080
    listener, err := net.Listen("tcp", ":8080")
    if err != nil {
        log.Fatal("Listen error:", err)
    }
    defer listener.Close()
    
    fmt.Println("Server listening on :8080")
    
    for {
        // Принимаем входящее соединение
        conn, err := listener.Accept()
        if err != nil {
            log.Println("Accept error:", err)
            continue
        }
        
        // Обрабатываем в отдельной горутине
        go handleConnection(conn)
    }
}

func handleConnection(conn net.Conn) {
    defer conn.Close()
    
    // Читаем данные от клиента
    buffer := make([]byte, 1024)
    n, err := conn.Read(buffer)
    if err != nil {
        log.Println("Read error:", err)
        return
    }
    
    message := string(buffer[:n])
    fmt.Printf("Получено: %s\n", message)
    
    // Отправляем ответ
    response := fmt.Sprintf("Вы отправили: %s", message)
    conn.Write([]byte(response))
}

Пример 2: TCP Клиент

package main

import (
    "fmt"
    "log"
    "net"
)

func main() {
    // Подключаемся к серверу
    conn, err := net.Dial("tcp", "localhost:8080")
    if err != nil {
        log.Fatal("Connection error:", err)
    }
    defer conn.Close()
    
    // Отправляем сообщение
    message := "Hello from client"
    _, err = conn.Write([]byte(message))
    if err != nil {
        log.Fatal("Write error:", err)
    }
    
    // Получаем ответ
    buffer := make([]byte, 1024)
    n, err := conn.Read(buffer)
    if err != nil {
        log.Fatal("Read error:", err)
    }
    
    response := string(buffer[:n])
    fmt.Println("Ответ сервера:", response)
}

Пример 3: HTTP Сервер (TCP поверх)

HTTP использует TCP под капотом:

package main

import (
    "fmt"
    "net/http"
)

func main() {
    // net.http.Server слушает на TCP порту
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello World!")
    })
    
    http.HandleFunc("/api/users", func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-Type", "application/json")
        fmt.Fprintf(w, `{"users": ["Alice", "Bob"]}`)
    })
    
    // Слушаем на TCP :8080
    fmt.Println("HTTP Server on :8080")
    http.ListenAndServe(":8080", nil)
}

Пример 4: Чат (двусторонняя коммуникация)

package main

import (
    "bufio"
    "fmt"
    "log"
    "net"
    "strings"
)

func main() {
    listener, _ := net.Listen("tcp", ":3000")
    defer listener.Close()
    
    fmt.Println("Chat server on :3000")
    
    for {
        conn, _ := listener.Accept()
        go handleChat(conn)
    }
}

func handleChat(conn net.Conn) {
    defer conn.Close()
    
    reader := bufio.NewReader(conn)
    
    for {
        // Читаем строку (до \n)
        message, err := reader.ReadString(
)
        if err != nil {
            fmt.Println("Client disconnected")
            return
        }
        
        message = strings.TrimSpace(message)
        fmt.Printf("[Client]: %s\n", message)
        
        // Отправляем эхо
        response := fmt.Sprintf("Echo: %s\n", message)
        conn.Write([]byte(response))
    }
}

Пример 5: RPC сервер (удалённые вызовы процедур)

package main

import (
    "fmt"
    "log"
    "net"
    "net/rpc"
)

// Сервис с методами
type Math struct{}

func (m *Math) Add(args [2]int, reply *int) error {
    *reply = args[0] + args[1]
    return nil
}

func (m *Math) Multiply(args [2]int, reply *int) error {
    *reply = args[0] * args[1]
    return nil
}

func main() {
    // Регистрируем сервис
    math := new(Math)
    rpc.Register(math)
    
    // Слушаем TCP соединения
    listener, err := net.Listen("tcp", ":1234")
    if err != nil {
        log.Fatal(err)
    }
    defer listener.Close()
    
    fmt.Println("RPC server on :1234")
    
    for {
        conn, _ := listener.Accept()
        go rpc.ServeConn(conn)  // Обработка RPC вызовов
    }
}
// RPC клиент
package main

import (
    "fmt"
    "log"
    "net/rpc"
)

func main() {
    // Подключаемся к RPC серверу
    client, err := rpc.Dial("tcp", "localhost:1234")
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()
    
    // Вызываем удалённый метод
    var result int
    err = client.Call("Math.Add", [2]int{5, 3}, &result)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("5 + 3 =", result)  // Выведет 8
}

Пример 6: gRPC (современное RPC)

// service.proto
syntax = "proto3";

service Calculator {
  rpc Add(AddRequest) returns (AddResponse);
}

message AddRequest {
  int32 a = 1;
  int32 b = 2;
}

message AddResponse {
  int32 result = 1;
}
// server.go
package main

import (
    "context"
    "fmt"
    "log"
    "net"
    "google.golang.org/grpc"
)

type Server struct{}

func (s *Server) Add(ctx context.Context, req *AddRequest) (*AddResponse, error) {
    return &AddResponse{Result: req.A + req.B}, nil
}

func main() {
    listener, _ := net.Listen("tcp", ":50051")
    grpcServer := grpc.NewServer()
    RegisterCalculatorServer(grpcServer, &Server{})
    grpcServer.Serve(listener)  // Слушаем TCP
}

Пример 7: Прокси сервер

package main

import (
    "fmt"
    "io"
    "log"
    "net"
)

func main() {
    listener, _ := net.Listen("tcp", ":9000")
    defer listener.Close()
    
    fmt.Println("Proxy on :9000 -> :8080")
    
    for {
        clientConn, _ := listener.Accept()
        go proxy(clientConn)
    }
}

func proxy(clientConn net.Conn) {
    defer clientConn.Close()
    
    // Подключаемся к целевому серверу
    serverConn, err := net.Dial("tcp", "localhost:8080")
    if err != nil {
        log.Println("Cannot connect to server:", err)
        return
    }
    defer serverConn.Close()
    
    // Двусторонняя передача данных
    go io.Copy(serverConn, clientConn)  // Клиент -> Сервер
    io.Copy(clientConn, serverConn)     // Сервер -> Клиент
}

Пример 8: Подключение к существующему сервису

func ConnectToDatabase(host string, port int) (net.Conn, error) {
    addr := fmt.Sprintf("%s:%d", host, port)
    
    // TCP соединение к БД (например PostgreSQL)
    conn, err := net.Dial("tcp", addr)
    if err != nil {
        return nil, fmt.Errorf("database connection failed: %w", err)
    }
    
    return conn, nil
}

// MySQL
var db, _ = sql.Open("mysql", "user:password@tcp(localhost:3306)/dbname")

// PostgreSQL
var db, _ = sql.Open("postgres", "user=postgres host=localhost port=5432 dbname=testdb sslmode=disable")

Ключевые функции TCP в Go

ФункцияНазначение
net.Listen("tcp", addr)Создать TCP сервер
net.Dial("tcp", addr)Подключиться к TCP серверу
listener.Accept()Принять входящее соединение
conn.Read()Прочитать данные
conn.Write()Отправить данные
conn.Close()Закрыть соединение
bufio.Scanner()Читать строками

Заключение

ТCP в Go используется для:

  • HTTP/REST сервисов (основа веб-приложений)
  • Микросервисной архитектуры (gRPC, RPC)
  • Баз данных (PostgreSQL, MySQL на TCP портах)
  • Чатов и real-time приложений
  • Прокси и балансировщиков нагрузки
  • Любых приложений требующих надёжной доставки
Приведи примеры использования TCP | PrepBro