Закрытие сокетных соединений после связи - PullRequest
0 голосов
/ 20 февраля 2020

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

Кажется, что все работает должным образом, за исключением постепенного завершения соединений net.Conn, когда клиент отключается , Ниже приведена реализация, которую я имею в настоящее время. Ниже приведены некоторые комментарии о коде.

package main

import (
    "fmt"
    "net"
    "bufio"
)

const localAddr = "127.0.0.1:8001"
const remoteAddr = "127.0.0.1:8002"

func main() {
    fmt.Println("Starting")
    listener, err := net.Listen("tcp", "127.0.0.1:8001")
    if err != nil {
        fmt.Println(err)
    }

    for {
        fmt.Println("Awaiting connection")
        src, err := listener.Accept()
        if err != nil {
            fmt.Println(err)
            continue
        }

        fmt.Printf("Connection accepted from %s\r\n", src.LocalAddr().String())

        dialer := &net.Dialer{}
        dst, err := dialer.Dial("tcp", remoteAddr)
        if err != nil {
            fmt.Printf("Error dialing %s\r\n", remoteAddr)
            continue
        }

        go forwarder("outgoing", src, dst)
        go forwarder("incoming", dst, src)
    }
}

func forwarder(id string, src, dst net.Conn) {
    input := bufio.NewScanner(src)
    for input.Scan() {
        b := input.Bytes()
        _, err := dst.Write(b)
        if err != nil {
            fmt.Printf("Forwarding error: %v\r\n", err)
        } else {
            fmt.Println(input.Text())
        }
    }

    if err := input.Err(); err != nil {
        fmt.Printf("Source connection (%s) closed unexpectedly: %v", id, err)
    }

    if err := src.Close(); err != nil {
        fmt.Printf("Error closing source connection (%s): %v\r\n", id, err)
    } else {
        fmt.Printf("Source connection (%s) closed gracefully\r\n", id)
    }

    if err := dst.Close(); err != nil {
        fmt.Printf("Error closing destination connection (%s): %v\r\n", id, err)
    } else {
        fmt.Printf("Destination connection (%s) closed gracefully\r\n", id)
    }
}

Итак, в конце функции main() имеется бесконечный l oop, который принимает новые клиентские соединения, создает для каждого новое соединение для набора номера, а затем запускает две процедуры передачи траффи c от одного к другому и наоборот.

Функция forwarder() - это место, где происходит передача сообщений. for input.Scan() l oop блокируется до тех пор, пока клиент не закроет соединение или не произойдет ошибка соединения - по крайней мере, я так понимаю и как это работает, когда я подключаюсь с терминала, используя nc 127.0.0.1 8001. Все, что я печатаю на терминале, затем доставляется прослушивателю прокси и пересылается в восходящем направлении. На входящей стороне у меня есть простой эхо-сервер только для тестирования, поэтому сообщение снова отправляется обратно в терминал. Крутые бананы!

Когда я закрываю соединение с терминала с помощью Ctrl C. Программа, которая передает сообщения от слушателя на номеронабиратель, как и ожидалось, выходит из for input.Scan() l oop без ошибок и закрывает соединения слушателя и номеронабирателя. Все идет нормально. Но проблема в том, что вторая процедура, которая передает сообщения от номеронабирателя слушателю, теперь выходит из for input.Scan() l oop из-за ошибки (использование закрытого сетевого соединения), а затем все еще пытается закрыть два соединения, которые явно не работают , Должен ли я просто игнорировать эти ошибки и продолжать свою жизнь или есть более элегантный способ закрыть обе связи?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...