注意
我将这个问题改写为悬赏单,因为我能够弄清楚如何解决第一个问题,但不想开始一个新的问题。以下评论与原始问题有关,而不是与之相关的。
问题描述
我的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)
}
}
答案 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')
时,这是必需的原因。因此,响应末尾包含换行符,在阅读响应文本时,您应该阅读该换行符。