Golang同时从TCP Connectoin读取

时间:2018-10-15 17:30:06

标签: go networking concurrency

我在Go项目中遇到了一些问题。该代码太大了,无法复制和粘贴,因此我将尽力解释。

我的程序首先连接到TCP服务器,然后启动一个goroutine,将连接对象作为参数传递。

我要实现的目标是让客户端从tcp连接中进行无限读取,同时通过发送检索数据来获取用户输入并与服务器进行通信。我曾尝试使用另一个goroutine,但是无论何时尝试从服务器检索数据,程序都会阻塞。

这是去操场上的错误的再现。

https://play.golang.org/p/OD5ozCRmy_4服务器

https://play.golang.org/p/t1r_BAQM-jn客户

基本上,每当客户端尝试从连接读取时,它都会卡住。 谢谢您的帮助。

1 个答案:

答案 0 :(得分:0)

您应该使用频道 这是一个可以接收一些连接的示例,每个连接都可以按需发送数据

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)
}