Почему кажется, что net.Conn.close() закрывается в неподходящее время?

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

    package main
    
    import (
        "bufio"
        "fmt"
        "io"
        "log"
        "net"
        "strconv"
        "strings"
        "time"
    )
    
    
    
    func main() {
        listener, err := net.Listen("tcp", "localhost:8000")
        if err != nil {
            log.Fatal(err)
        }
        for {
            conn, err := listener.Accept()
            if err != nil {
                log.Print(err)
            }
            go handleConn(conn)
            conn.Close()
        }
    
    }
    
    func handleConn(someconnection net.Conn) {
        func1(someconnection)
        func2(someconnection) //connection drops in the middle of executing this part
    }
func func2(someconnection net.Conn) {

    //send message(a string)
    _, err := io.WriteString(someconnection, dosomething)
    if err != nil {
        log.Fatal(err)
    }
    //await reply
    //send another message
    _, err = io.WriteString(someconnection, dosomething)
    if err != nil {
        log.Fatal(err)
    }
   //await reply

    //send another message, connection tends to close somewhere here
    _, err = io.WriteString(someconnection, dosomething)
    if err != nil {
        log.Fatal(err)
    }

    //await,send
    _, err = io.WriteString(someconnection, do something)
    if err != nil {
        log.Fatal(err)
    }

    //await, read and print message
    c := bufio.NewReader(someconnection)
    buff1 := make([]byte, maxclientmessagelength)
    buff1, err = c.ReadBytes(delimiter)

    fmt.Printf("\n%s\n", buff1)

    _, err = io.WriteString(someconnection, dosomething)
    if err != nil {
        log.Fatal(err)
    }
}

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

Обновление 1:

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

func main() {
listener, err := net.Listen("tcp", "localhost:8000")
if err != nil {
    log.Fatal(err)
}
for {
    conn, err := listener.Accept()
    if err != nil {
        log.Print(err)
    }
    defer conn.Close()
    go handleConn(conn)
}}

Теперь он не обязательно закрывается в течение секунды, я надеюсь, что он закроется, но, по крайней мере, теперь он проходит полностью.

Вы можете закрыть соединение внутри handleConn

Tiago Peczenyj 22.04.2022 21:49

@TiagoPeczenyj попробовал это. Проблема сохраняется, но, по крайней мере, иногда она закрывает соединение в нужное время.

Onlyartist9 22.04.2022 21:51
3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
0
2
65
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Горутины асинхронны, поэтому после вызова handleConn здесь:

go handleConn(conn)
conn.Close()

основная функция продолжает выполняться и закрывает соединение. Попробуйте просто регулярно вызывать функцию handleConn (без go).

Или переместите conn.Close() в последнюю строку handleConn, чтобы у вас могло быть несколько одновременных подключений.

Dylan Reimerink 22.04.2022 21:39

@DylanReimerink да. я собирался отредактировать ответ, потому что я только что заметил, что вызов находится внутри цикла for, и, возможно, OP хочет, чтобы все они были параллельными

Fedex7501 22.04.2022 21:41

@DylanReimerink да, я планировал запустить несколько одновременных подключений, но сейчас я пытаюсь протестировать одно.

Onlyartist9 22.04.2022 21:46

@ Fedex7501 по какой-то причине проблема все еще сохраняется.

Onlyartist9 22.04.2022 21:47

@ Fedex7501 задержка ... Однажды это сработало правильно, но после повторного вызова клиента это не удалось. Поэтому, хотя он работает сейчас, он кажется непоследовательным.

Onlyartist9 22.04.2022 21:49

это кажется намного сложнее диагностировать tbh

Fedex7501 23.04.2022 02:06

@ Fedex7501 может ли это быть связано со временем и тайм-аутом? Первая функция использует NewReader, но это не проблема. Там, где сервер имеет тенденцию к отключению, находится где-то во второй функции.

Onlyartist9 23.04.2022 05:54

conn.Close нужно сделать ПОСЛЕ того, как handleConn выполнит свою работу. Вы можете связаться с основным потоком, используя каналы, но это будет слишком сложно (а также заблокировать выполнение основного потока). Вот как это должно быть сделано

func main() {
    listener, err := net.Listen("tcp", "localhost:8000")
    if err != nil {
        log.Fatal(err)
    }
    for {
        conn, err := listener.Accept()
        if err != nil {
            log.Print(err)
        }
        go handleConn(conn)
        // REMOVE BELOW LINE
        // conn.Close()
    }
}

Добавьте conn.Close внутрь handleConn

func handleConn(someconnection net.Conn) {
    // ADD BELOW LINE
    defer someconnection.Close()
    func1(someconnection)
    func2(someconnection)
}

Это гарантирует, что conn.Close вызывается ПОСЛЕ func1 и func2 выполняется.

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