Я пытаюсь реализовать довольно простой прокси сокета 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 из-за ошибки (использование закрытого сетевого соединения), а затем все еще пытается закрыть два соединения, которые явно не работают , Должен ли я просто игнорировать эти ошибки и продолжать свою жизнь или есть более элегантный способ закрыть обе связи?