doutang2017 2018-06-29 16:53
浏览 73
已采纳

TCP服务器在第一个响应后失败

NOTE

I rewrote this question for the bounty as i was able to figure out how to get the first question solved but didn't want to start a new question. the comments below pertain to the original question, not the revised.

Description of Issue

My tcp client executes querying the tcp server one time successfully, returns the response, and then subsequent requests to the server from the client fails. Also, if i terminate the client and reload it fails on the first attempt as well.

Here's what my command prompt looks like:

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

What I expect

I expect to be able to query the tcp server from the tcp client endlessly, and have the tcp server return a response from the UDP Server every time. Also, if i terminate the tcp client and reload it should also query correctly to the tcp server without hiccups.

What I think

Something is incorrect with the tcp server accepting connections. I moved the UDP Portion in separate code (not here as not important still does not work) to its own function which opens and closes UDP connections and it still does not function after first connection.

UPDATE

I updated the code to display "Accepted Connection" just below c,err:=serverConn.Accept() and it only printed once, for the first request. any subsequent queries from the client did not display the line so it has to do with accepting connections

Sourcecode

Server Code:

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

Client Code:

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('
')
      // send to socket
    fmt.Fprintf(conn, text + "
")
    // listen for reply
    message, _ := bufio.NewReader(conn).ReadString('
')
    fmt.Print("Message from server: "+message)
  }
}
  • 写回答

1条回答 默认 最新

  • dqnz43863 2018-07-03 03:45
    关注

    It seems there are two problems here:

    1) UDP Server

    Your question describes an issue when the client is not able to make a second request to the server.

    I used a simple echo UDP server, along with the code you posted for the server and client and can't reproduce the problem (I can still make several requests to the server), so I suspect that has to do with the UDP server you are using (code for which I can't see in this question).

    I suggest you try this with a simple UDP server that just echoes messages back:

    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) Extra new line in TCP Client

    Using the exact code you posted and that UDP server I posted above, this seems to work, but the output I get on the client is not what I would have expected.

    It seems that is cause by a second issue which is this line in the client:

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

    That line end you are sending is causing the scanner you use on the server to read two lines (the text you send and then an empty line), making the server write two lines back to the client.

    But in the client you only read one line, so the second line seems to be pending until the client connects again.

    That can be fixed by simply changing that to:

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

    Output for the fixed code

    Using that UDP server and making that change to the client, this is the output I get when running all three components:

    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: 
    

    I can then stop just the client, start it again and it'd keep working:

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

    Aditional notes

    About the two other lines in the client code that use newlines:

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

    That newline is needed there, cause when you input the text using standard input, you finish the line using the enter key (and thus ending the line with a newline), so the line should be read until the character.

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

    That one is needed cause when the server writes the response to the connection it does w.WriteString(response+" "). So the response includes a newline at the end, and you should read up to that newline when reading the response text.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 机器学习能否像多层线性模型一样处理嵌套数据
  • ¥20 西门子S7-Graph,S7-300,梯形图
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效