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

标签 sockets go tcp udp

注意

我为了赏金重写了这个问题,因为我能够弄清楚如何解决第一个问题,但不想开始一个新问题。下面的评论与原始问题有关,而不是修改后的问题。

问题描述

我的tcp client执行一次查询tcp server成功,返回response,然后client对server的后续请求都失败了。另外,如果我终止客户端并重新加载,它在第一次尝试时也会失败。

这是我的命令提示符:

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 Server返回一个响应。此外,如果我终止 TCP 客户端并重新加载它也应该正确查询到 TCP 服务器而不会出现问题。

我的想法

接受连接的 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) 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')

那里需要换行符,因为当您使用标准输入输入文本时,您使用回车键结束该行(因此以换行符结束该行),因此应该读取该行直到 \n 字符。

message, _ := bufio.NewReader(conn).ReadString('\n')

这是必需的,因为当服务器将响应写入它所做的连接时 w.WriteString(response+"\n")。因此,响应在末尾包含一个换行符,您在阅读响应文本时应该阅读到该换行符。

关于sockets - 第一次响应后 TCP 服务器失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51106346/

相关文章:

c++ - TCP over IPv4 的最小数据包大小是多少

vb6 winsock 控件 RemoteHostIP 截断 IP 地址的最后一位

java - 为什么线程中的公共(public)方法无法在 onCreate 中解析?

java - 通过套接字发送 10 MB 的缓冲区 - block 还是整个 10MB?

c - 尝试在c中将结构的一部分从tcp服务器发送到客户端

go - 我可以创建一个与另一个签名相同的函数吗?

variables - Golang 的 init() 函数中的包范围变量赋值

node.js - 如何在 Node.js 中结合使用 express 和 tcp-socket

multithreading - 在 TCP 客户端服务器中循环读取和写入数据时的并发问题

mysql - Perl Web 应用程序问题 : DBI connect failed: Can't create TCP/IP socket (10106)