Golang одновременно читает из TCP-соединения - PullRequest
0 голосов
/ 15 октября 2018

У меня возникли проблемы с проектом Go.Код слишком велик, чтобы его можно было скопировать и вставить, поэтому я постараюсь объяснить как можно лучше.

Моя программа сначала подключается к TCP-серверу, а затем запускает процедуру передачи в качестве аргумента объекта подключения.

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

Вот воспроизведение ошибки на игровой площадке.

https://play.golang.org/p/OD5ozCRmy_4 server

https://play.golang.org/p/t1r_BAQM-jn client

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

1 Ответ

0 голосов
/ 18 октября 2018

Вы должны использовать канал. Вот пример, который может принимать некоторые соединения, и каждое соединение может отправлять данные по желанию.

пакет tcp

import (
    "bufio"
    "fmt"
    "net"
    "strconv"

    "../log"

    "../config"
    "../controllers"
    h "../helpers"
    )

    type msgFormat struct {
      text []byte
      net.Conn
    }

var accounts = make(map[net.Conn]int)
var conns = make(chan net.Conn)
var dconns = make(chan net.Conn)
var msgs = make(chan msgFormat)
var i int

//Init is first point
func Init() {
    startserver()
    for {
        select {
        case conn := <-conns:
            handleconnect(conn)
        case msg := <-msgs:
            go handlemsg(msg)
        case dconn := <-dconns:
            handlediscounect(dconn)
        }
    }
}
func handlemsg(incomemsg msgFormat) {
    logger.Log.Println(string(incomemsg.text))
    resp, err := controllers.Do(incomemsg.text)
    if err != nil {
        logger.Log.Println(err.Error())
    }
    strLen := []byte(h.Lpad(string(fmt.Sprintf("%v", len(resp))), "0", 4))
    //
    fresponse := append(strLen, resp...)

    incomemsg.Write(fresponse)
    logger.Log.Println("response is %v" , string(fresponse))
}

func startserver() {
    conf := config.GetConfigInstance()

    ln, err := net.Listen(conf.SERVER.Nettype, conf.SERVER.Address)
    if err != nil {
        logger.Log.Println(err.Error())
    }
    logger.Log.Printf("server is serving at %v", conf.SERVER.Address)
    go func() {
        for {
            conn, err := ln.Accept()
            if err != nil {
                logger.Log.Println(err.Error())
            }
            conns <- conn
        }
    }()

}

func readdate(conn net.Conn, i int) {
    for {
        rd := bufio.NewReader(conn)

        dataLen := make([]byte, 4)
        _, err := rd.Read(dataLen)
        if err != nil {
            break
        }
        intLen, _ := strconv.Atoi(string(dataLen))
        data := make([]byte, intLen)
        _, err = rd.Read(data)
        if err != nil {
            break
        }
        msgs <- msgFormat{data, conn}
    }
    dconns <- conn
}

func handleconnect(newconnection net.Conn) {
    accounts[newconnection] = i
    i++
    // if addr , ok := newconnection.RemoteAddr().str
    logger.Log.Printf("Action: Client_Connected %v is connected via %v \n", i, newconnection.RemoteAddr().(*net.TCPAddr).IP)
    go readdate(newconnection, i)
}

func handlediscounect(disconnection net.Conn) {
    logger.Log.Printf("Action: Client_Disconnected %v / %v is gone\n", accounts[disconnection] + 1, disconnection.RemoteAddr().(*net.TCPAddr).IP)
    delete(accounts, disconnection)
}
...