第一次响应后,TCP服务器失败

时间:2018-06-29 16:53:39

标签: sockets go tcp udp

注意

我将这个问题改写为悬赏单,因为我能够弄清楚如何解决第一个问题,但不想开始一个新的问题。以下评论与原始问题有关,而不是与之相关的。

问题描述

我的tcp客户端成功一次执行了一次查询tcp服务器的操作,返回了响应,然后客户端对该服务器的后续请求失败。另外,如果我终止客户端并重新加载,它也会在第一次尝试时失败。

这是我的命令提示符:

root@ubuntuT:/home/jon/gocode/udps#  ./udpservtcpclient 
Text to send: SampleQuery
Message from server: SampleResponse
Text to send: SampleQuery
((End - No Response))
root@ubuntuT:/home/jon/gocode/udps# ./udpservtcpclient 
Text to send: SampleQuery
((End - No Response))

我期望的结果

我希望能够无休止地从tcp客户端查询tcp服务器,并使tcp服务器每次都从UDP服务器返回响应。另外,如果我终止tcp客户端并重新加载,它也应该正确地查询tcp服务器,而不会打h。

我的想法

tcp服务器接受连接时出现某些错误。我将单独的代码中的UDP部分移到了它自己的函数中,该部分可以打开和关闭UDP连接,但在第一次连接后仍然不起作用。

更新

我更新了代码,以在“ c,err:=serverConn.Accept()”下方显示“ Accepted Connection”,并且对于第一个请求,它仅打印了一次。来自客户端的任何后续查询都不会显示该行,因此与接受连接有关

源代码

服务器代码:

package main

import (
  "log"
  //"fmt"
  "net"
  //"strings"
  "bufio"
  //"time"
  //"github.com/davecgh/go-spew/spew"
)

var connUDP *net.UDPConn

func udpRoutine(query string)(string){
  connUDP.Write([]byte(query))
  buf:= make([]byte,128)
  n,err:=connUDP.Read(buf[0:])
  if err != nil{
    log.Fatal(err)
  }
  response := string(buf[0:n])
  return response
}

func handle(conn net.Conn) error {
  defer func(){
    conn.Close()
  }()
  r := bufio.NewReader(conn)
  w := bufio.NewWriter(conn)
  scanr := bufio.NewScanner(r)
  for {
    scanned := scanr.Scan()
    if !scanned {
      if err := scanr.Err(); err != nil {
    log.Printf("%v(%v)", err, conn.RemoteAddr())
    return err
      }
      break
    }
    response:=udpRoutine(scanr.Text())
    w.WriteString(response+"\n")
    w.Flush()
  }
  return nil
}

func main(){

   // setup tcp listener
   serverConn,err := net.Listen("tcp","127.0.0.1:8085")
   if err != nil{
    log.Fatal(err)
   }
   defer serverConn.Close()

   // setup udp client
   udpAddr,err:=net.ResolveUDPAddr("udp4","127.0.0.1:1175")
   if err != nil{
    log.Fatal(err)
   }
   connUDP,err=net.DialUDP("udp",nil,udpAddr)
   if err != nil{
    log.Fatal(err)
   }
   defer connUDP.Close()

   for{
      c,err:=serverConn.Accept()
      if err != nil{
    log.Fatal(err)
      }
      //c.SetDeadline(time.Now().Add(5))
      go handle(c)
    }
  }

客户代码:

package main

import "net"
import "fmt"
import "bufio"
import "os"

func main() {

  // connect to this socket
  conn, _ := net.Dial("tcp", "127.0.0.1:8085")
  for { 
    reader := bufio.NewReader(os.Stdin)
    // read in input from stdin
    fmt.Print("Text to send: ")
    text,_ := reader.ReadString('\n')
      // send to socket
    fmt.Fprintf(conn, text + "\n")
    // listen for reply
    message, _ := bufio.NewReader(conn).ReadString('\n')
    fmt.Print("Message from server: "+message)
  }
}

1 个答案:

答案 0 :(得分:2)

这里似乎有两个问题:

1)UDP服务器

您的问题描述了客户端无法向服务器发出第二个请求时的问题。

我使用了一个简单的echo UDP服务器,以及您为服务器和客户端发布的代码,但无法重现该问题(我仍然可以向服务器发出多个请求),因此我怀疑这与您正在使用的UDP服务器(我在此问题中看不到的代码)。

我建议您使用简单的UDP服务器尝试一下,该服务器仅将消息回显:

package main

import (
    "fmt"
    "net"
)

func main() {
    conn, _ := net.ListenUDP("udp", &net.UDPAddr{IP:[]byte{0,0,0,0},Port:1175,Zone:""})
    defer conn.Close()
    buf := make([]byte, 1024)
    for {
        n, addr, _ := conn.ReadFromUDP(buf)
        conn.WriteTo(buf[0:n], addr)
        fmt.Println("Received ", string(buf[0:n]), " from ", addr)
    }
}

2)TCP客户端中的额外新行

使用您发布的确切代码以及我在上面发布的UDP服务器,这似乎可以正常工作,但是我在客户端上获得的输出却不是我期望的。

似乎是由第二个问题引起的,这是客户端中的这一行:

// send to socket
fmt.Fprintf(conn, text + "\n")

您要发送的那一行末端导致您在服务器上使用的扫描仪读取两行(您发送的文本,然后是一个空行),从而使服务器将两行写回到客户端。

但是在客户端中,您只能读取一行,因此第二行似乎在等待客户端重新连接之前处于挂起状态。

只需将其更改为:

// send to socket
fmt.Fprintf(conn, text)

固定代码输出

使用该UDP服务器并对客户端进行更改,这是我在运行所有三个组件时得到的输出:

Text to send: first msg
Message from server: first msg
Text to send: second msg
Message from server: second msg
Text to send: third msg
Message from server: third msg
Text to send: 

然后我可以仅停止客户端,重新启动它,然后它将继续工作:

Text to send: fourth msg
Message from server: fourth msg
Text to send: 

附加说明

关于客户端代码中使用换行符的其他两行:

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

在那里需要换行符,这是因为当您使用标准输入输入文本时,您使用回车键结束了该行(并因此以换行符结束该行),因此应该读取该行,直到{{1} }。

\n

当服务器将响应写入到它所做的连接message, _ := bufio.NewReader(conn).ReadString('\n') 时,这是必需的原因。因此,响应末尾包含换行符,在阅读响应文本时,您应该阅读该换行符。