【问题标题】:A receiving and sending TCP client with Go使用 Go 接收和发送 TCP 客户端
【发布时间】:2019-02-13 17:45:50
【问题描述】:

我正在尝试在不使用任何库的情况下实现自己的 P2P 网络。我想构建一个 TCP 客户端来发送和接收来自其他节点的消息。所以所有节点都应该能够通过 tcp/ip 发送和接收消息。

我目前的问题是当我启动两个客户端时:一个节点能够接收和发送消息,但另一个节点只是发送消息而无法接收消息。

我想我需要以某种方式实现一个通道,但我对 Go 真的很陌生,不知道如何实现它。有什么建议么?

代码如下:

Main.go:

package main

 func main() {

  address := "127.0.0.1:8081" // IP of the other node; hardcoded for now
  go startServer()
  startClient(address)

} 

helpler.go:

package main

import (
 "bufio"
 "fmt"
 "net"
 "os"
) 

func startClient(address string) {
 //connect to this socket
 connClient, _ := net.Dial("tcp", address)

for {

    //read in input from stdin
    reader := bufio.NewReader(os.Stdin)
    fmt.Print("Text to send: ")
    text, _ := reader.ReadString('\n')

    //send to socket
    fmt.Fprint(connClient, text+"\n")

    //listen for reply
    //message, _ := bufio.NewReader(connClient).ReadString('\n')
    //fmt.Print("Message from server: " + message)
  }
 }
func startServer() {
 fmt.Println("Starting...")

//listen on all interfaces
ln, _ := net.Listen("tcp", ":8081")

//accept connection on port
connServer, _ := ln.Accept()

//run loop forever
for {
    //will listen for message to process ending in newline(\n)
    message, _ := bufio.NewReader(connServer).ReadString('\n')

    //fmt.Print("Message Received:" + string(message))

    //sample process for string received
    //newmessage := strings.ToUpper(message)

    connServer.Write([]byte(message + "\n"))
  }
 }

【问题讨论】:

  • 一个问题是 StartServer 中的循环创建并丢弃 bufio.Reader 以及该读取器缓冲的任何数据。每个连接创建一次 bufio.Readers。
  • 谢谢,但它是在循环中创建双向通道,以便在节点之间发送无休止的消息。不仅仅是发送“ping”
  • 程序丢弃缓冲数据。那可能不是你想要的。此外,ReadString 返回的值包括跟踪 \n。另一个 \n 在写入时添加。如果您不打算在每条消息中都发送一个空行,则不要添加额外的 \n。
  • 不要忽略错误。您不能让两台服务器在同一个主机:端口上侦听。
  • 你的意思是发送消息一个端口和接收消息一个端口?

标签: go p2p tcp-ip


【解决方案1】:

这里是新手 Go 开发人员,但我可以立即想到一个问题。不能有多个进程监听同一个 IP 和端口。

您可能对此有疑问,但是因为您没有检查错误,所以您没有发现它。如果您有代码来检查错误,您可能会注意到您收到如下错误:

2018/07/11 09:21:06 监听 tcp 127.0.0.1:8081: bind: address already

使用退出状态1

即使这不是您的问题,进行错误检查仍然是个好主意。

我建议您添加支票。例如

服务器端

ln, err := net.Listen("tcp", "127.0.0.1:8081")
if err != nil {
    log.Fatal(err)
}

客户端

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

我想我需要以某种方式实现一个频道

如上所述,我自己是 Go 新手,但我的理解是通道是同一程序中的进程间通信工具。与多个程序无关。如果您在自己喜欢的搜索工具中搜索 go 频道,您可以找到更多信息,但不要相信这就是您要查找的内容。

【讨论】:

    【解决方案2】:

    尝试使用两个不同的进程作为服务器和客户端。

    例如在主函数处:

    func main() {
        connType := os.Getenv("TYPE")
    
        if connType == "server" {
            startServer()
        } else if connType == "client" {
            startClient()
        } else {
            log.Println("please provide the TYPE arg (TYPE=server or TYPE=client)")
        }
    }
    

    然后你可以运行TYPE=server go run yourappTYPE=client go run yourapp。 你可以看看这个 GitHub repo https://github.com/johannesridho/protobuf-over-tcp

    【讨论】:

      猜你喜欢
      • 2017-09-02
      • 1970-01-01
      • 1970-01-01
      • 2012-10-17
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      • 2018-09-19
      • 2015-01-16
      相关资源
      最近更新 更多