golang соединение не пишет, пока я не закрою соединение или не выйду из своего клиентского приложения - PullRequest
1 голос
/ 19 апреля 2020

Я новичок в golang и пытаюсь создать простой TCP-сервер и клиент в go. Клиент отправляет сообщение на сервер «привет от клиента» и будет ждать ответа от сервера с сообщением «Успешно обработано». Проблема в том, что клиент не сбрасывает данные до тех пор, пока я не вызову conn.Close () или не нажму CTRL + C на клиенте, если я нажму CTRL + C или закрою соединение, которое клиент завершает, но не ожидает сообщения сервера. Сервер застревает на этой линии

n, copyErr := io.Copy(temp, conn)

Может кто-нибудь, пожалуйста, помогите мне с этим.

клиент. go

package main

import (
    "fmt"
    "io/ioutil"
    "net"
)

func writeMessage(conn net.Conn) {
    msg := "Hello from Client"
    _, writeErr := conn.Write([]byte(msg))
    if writeErr != nil {
        fmt.Println("Write error", writeErr)
    }


}

func main() {
    conn, err := net.Dial("tcp", "127.0.0.1:8080")
    if err != nil {
        fmt.Println("Dial error", err)
    }
    writeMessage(conn)

    msg, err := ioutil.ReadAll(conn)
    fmt.Println("Received message", string(msg), "from", conn.RemoteAddr())
}

сервер. go

package main

import (
    "bytes"
    "fmt"
    "io"
    "net"
    "os"
)

func handleConn(conn net.Conn) {
    localAddr := conn.LocalAddr()
    fmt.Println("Handling connection for", localAddr)

    temp := new(bytes.Buffer)
    n, copyErr := io.Copy(temp, conn)

    if copyErr != nil {
        fmt.Println("Copy error:", copyErr)
    }

    fmt.Println("Processed", n, "bytes")
    conn.Write([]byte("Successfully processed"))

}

func main() {
    ln, err := net.Listen("tcp", ":8080")
    if err != nil {
        fmt.Println("Error creating TCP server")
        os.Exit(1)
    }

    fmt.Println("Listening on port :8080")

    for {
        conn, err := ln.Accept()
        if err != nil {
            fmt.Println("Connection error")
        }
        handleConn(conn)
    }

}

1 Ответ

2 голосов
/ 19 апреля 2020

Код застрял на n, copyErr := io.Copy(temp, conn), потому что он не получает EOF, пока не будет закрыто входящее соединение (либо путем вызова Close(), либо при закрытии программы). В вашем случае вы хотите закрыть только сторону записи соединения. Для этого TCPConn реализует метод CloseWrite. Вот пример, как вы можете его использовать:

func writeMessage(conn net.Conn) error {
    if  cw, ok := conn.(interface{ CloseWrite() error }); ok {
        defer cw.CloseWrite()
    } else {
        return fmt.Errorf("Connection doesn't implement CloseWrite method")
    }

    msg := "Hello from Client"
    _, writeErr := conn.Write([]byte(msg))
    if writeErr != nil {
        fmt.Println("Write error", writeErr)
    }

    return nil
}
...