>  기사  >  백엔드 개발  >  골랑 포워드 TCP

골랑 포워드 TCP

WBOY
WBOY원래의
2023-05-16 14:45:37723검색

Go 언어에서는 TCP 연결을 만들고 관리하는 것이 매우 쉽습니다. 이 기사에서는 Go 언어를 사용하여 TCP 서비스를 만들고 TCP 연결을 전달하는 방법을 소개합니다.

  1. 전제 지식

이 기사를 공부하기 전에 다음 기본 지식 사항을 숙지해야 합니다.

  • Go 언어의 기본 지식
  • TCP 프로토콜의 기본 개념 및 사용법
  1. TCP 서비스 만들기

Go 언어에서는 TCP 서비스를 만드는 것이 매우 간단합니다. 먼저 net 패키지와 bufio 패키지를 가져온 다음 net.Listen 메서드를 사용하여 포트 번호를 수신해야 합니다. net包和bufio包,然后使用net.Listen方法监听一个端口号:

package main

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

func main() {
    ln, err := net.Listen("tcp", ":8080")
    if err != nil {
        fmt.Println("Error listening:", err.Error())
        return
    }
    defer ln.Close()
    fmt.Println("Listening on port 8080...")
}

在上面的例子中,我们监听了8080端口号,并在控制台输出Listening on port 8080...

  1. 接受TCP连接

接下来,我们需要接受TCP连接。使用ln.Accept()方法可以在一个连接准备好之前阻塞程序。一旦有一个连接请求,我们就可以创建一个新协程,处理连接:

for {
    conn, err := ln.Accept()
    
    if err != nil {
        fmt.Println("Error accepting connection:", err.Error())
        return
    }
    fmt.Println("Connection accepted.")

    // 处理连接
    go handleConnection(conn)
}

func handleConnection(conn net.Conn) {
    // 处理连接
}

在上面的代码中,我们使用了一个无限循环来不断接受连接请求。当有连接请求时,我们会创建一个新的协程go handleConnection(conn)来处理连接。

  1. 处理TCP连接

接下来,我们需要对连接进行处理。对于每个客户端连接,我们需要将客户端发送的所有数据转发到另一个服务器上。可以使用bufio包来进行读取和写入。

func handleConnection(conn net.Conn) {
    defer conn.Close()
    
    remoteConn, err := net.Dial("tcp", "127.0.0.1:9090")
    if err != nil {
        fmt.Println("Error connecting to remote server:", err.Error())
        return
    }
    defer remoteConn.Close()

    go func() {
        defer conn.Close()
        defer remoteConn.Close()

        for {
            data, err := bufio.NewReader(conn).ReadString('
')
            if err != nil {
                fmt.Println("Error reading from conn:", err.Error())
                return
            }
            _, err = remoteConn.Write([]byte(data))
            if err != nil {
                fmt.Println("Error writing to remoteConn:", err.Error())
                return
            }
        }
    }()

    // 从remoteConn读取数据并转发到conn
    for {
        data, err := bufio.NewReader(remoteConn).ReadString('
')
        if err != nil {
            fmt.Println("Error reading from remoteConn:", err.Error())
            return
        }
        _, err = conn.Write([]byte(data))
        if err != nil {
            fmt.Println("Error writing to conn:", err.Error())
            return
        }
    }
}

上面的代码中,我们首先使用net.Dial方法连接到另一个服务器,然后开启两个协程:一个协程读取客户端发来的数据并转发给另一个服务器,另一个协程从服务器读取数据并转发给客户端。

需要注意的是,在每个协程中都要使用defer conn.Close()defer remoteConn.Close()

package main

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

func main() {
    ln, err := net.Listen("tcp", ":8080")
    if err != nil {
        fmt.Println("Error listening:", err.Error())
        return
    }
    defer ln.Close()
    fmt.Println("Listening on port 8080...")

    for {
        conn, err := ln.Accept()
        
        if err != nil {
            fmt.Println("Error accepting connection:", err.Error())
            return
        }
        fmt.Println("Connection accepted.")

        go handleConnection(conn)
    }
}

func handleConnection(conn net.Conn) {
    defer conn.Close()
    
    remoteConn, err := net.Dial("tcp", "127.0.0.1:9090")
    if err != nil {
        fmt.Println("Error connecting to remote server:", err.Error())
        return
    }
    defer remoteConn.Close()

    go func() {
        defer conn.Close()
        defer remoteConn.Close()

        for {
            data, err := bufio.NewReader(conn).ReadString('
')
            if err != nil {
                fmt.Println("Error reading from conn:", err.Error())
                return
            }
            _, err = remoteConn.Write([]byte(data))
            if err != nil {
                fmt.Println("Error writing to remoteConn:", err.Error())
                return
            }
        }
    }()

    for {
        data, err := bufio.NewReader(remoteConn).ReadString('
')
        if err != nil {
            fmt.Println("Error reading from remoteConn:", err.Error())
            return
        }
        _, err = conn.Write([]byte(data))
        if err != nil {
            fmt.Println("Error writing to conn:", err.Error())
            return
        }
    }
}

위의 예에서는 8080 포트 번호를 수신하고 콘솔에 Listening on port 8080...을 출력했습니다.
    1. TCP 연결 수락

    다음으로 TCP 연결을 수락해야 합니다. 연결이 준비될 때까지 프로그램을 차단하려면 ln.Accept() 메서드를 사용하세요. 연결 요청이 있으면 연결을 처리하기 위해 새 코루틴을 생성할 수 있습니다.

    rrreee
      위 코드에서는 무한 루프를 사용하여 연결 요청을 지속적으로 수락합니다. 연결 요청이 있으면 연결을 처리하기 위해 새로운 코루틴 go handlerConnection(conn)을 생성합니다.
      1. TCP 연결 처리

      다음으로 연결을 처리해야 합니다. 각 클라이언트 연결마다 클라이언트가 보낸 모든 데이터를 다른 서버로 전달해야 합니다. 읽고 쓰기 위해 bufio 패키지를 사용할 수 있습니다. 🎜rrreee🎜위 코드에서는 먼저 net.Dial 메서드를 사용하여 다른 서버에 연결한 다음 두 개의 코루틴을 시작합니다. 하나의 코루틴은 클라이언트가 보낸 데이터를 읽고 이를 다른 코루틴에 전달합니다. 한 서버, 다른 코루틴은 서버에서 데이터를 읽어 클라이언트에 전달합니다. 🎜🎜연결이 실수로 닫히지 않도록 각 코루틴에서 defer conn.Close()defer remoteConn.Close()를 사용해야 합니다. . 🎜🎜🎜전체 코드🎜🎜🎜전체 TCP 전달 서비스 코드는 다음과 같습니다. 🎜rrreee🎜🎜요약🎜🎜🎜Go 언어를 사용하면 TCP 연결을 쉽게 만들고 관리할 수 있습니다. 이 기사에서는 Go 언어를 사용하여 TCP 서비스를 생성하고 전달하는 방법을 소개합니다. 🎜

    위 내용은 골랑 포워드 TCP의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

    성명:
    본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.