Golang проверить tcp порт открыт

Мне нужно проверить, открыты ли на удаленном адресе определенные порты TCP или нет. Я решил использовать golang для этой цели. Вот моя попытка:

func raw_connect(host string, ports []string) {
  for _, port := range ports {
     timeout := time.Second
     conn, err := net.DialTimeout("tcp", host + ":" + port, timeout)
     if err != nil {
        _, err_msg := err.Error()[0], err.Error()[5:]
        fmt.Println(err_msg)
     } else {
        msg, _, err := bufio.NewReader(conn).ReadLine()
        if err != nil {
           if err == io.EOF {
              fmt.Print(host + " " + port + " - Open!\n")
           }
        } else {
           fmt.Print(host + " " + port + " - " + string(msg))
        }
        conn.Close()
     }
   }
 }

Это отлично работает для TCP-порта, когда приложение (например, SSH) сначала возвращает строку, я читаю ее и печатаю без промедления.

Однако, когда приложение выше TCP сначала ожидает команды от клиента (например, HTTP), возникает тайм-аут (предложение if err == io.EOF).

Этот тайм-аут довольно длинный. Мне нужно было бы знать немедленно, если порт открыт или нет.

Есть ли более подходящая техника для этой цели?

Большое спасибо!

Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
API ввода вопросов - это полезный инструмент для интеграции моделей машинного обучения, таких как ChatGPT, в приложения, требующие обработки...
5
0
15 934
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Чтобы проверить порт, вы можете проверить, было ли соединение успешным. Например:

func raw_connect(host string, ports []string) {
    for _, port := range ports {
        timeout := time.Second
        conn, err := net.DialTimeout("tcp", net.JoinHostPort(host, port), timeout)
        if err != nil {
            fmt.Println("Connecting error:", err)
        }
        if conn != nil {
            defer conn.Close()
            fmt.Println("Opened", net.JoinHostPort(host, port))
        }
    }
}

Возможно ли, что в случае ошибки переменная conn все равно будет отличаться от nil ? Просто интересно, почему бы не использовать оператор if.else if.

E235 09.04.2020 12:15

Нет, это невозможно. Это может быть if.else if или только if.else. Я думаю, это не имеет значения

Rustavil Nurkaev 12.04.2020 15:21

Это не работает, по крайней мере, в настоящее время, я просто ставил любые порты, и даже если он закрыт, он все равно говорил, что он открыт. Это просто пинг сервера, я думаю

Matteo 27.06.2020 11:26

@Madeo, может быть, у тебя открыты все порты. Это работает для меня.

Edwinner 09.08.2021 22:41

Проверьте несколько примеров портов

func tcpGather(ip string, ports []string) map[string]string {
    // check emqx 1883, 8083 port

    results := make(map[string]string)
    for _, port := range ports {
        address := net.JoinHostPort(ip, port)
        // 3 second timeout
        conn, err := net.DialTimeout("tcp", address, 3*time.Second)
        if err != nil {
            results[port] = "failed"
            // todo log handler
        } else {
            if conn != nil {
                results[port] = "success"
                _ = conn.Close()
            } else {
                results[port] = "failed"
            }
        }
    }
    return results
}

Он также работает для UDP? Я пробовал, но какой бы порт я ни поставил, он всегда говорит мне, что он открыт.

Matteo 27.06.2020 11:32

Telnet — это приложение, работающее по протоколу TCP. Соединение UDP невозможно проверить с помощью Telnet.

Eds_k 27.06.2020 16:15

Другие вопросы по теме