注意
我为了赏金重写了这个问题,因为我能够弄清楚如何解决第一个问题,但不想开始一个新问题。下面的评论与原始问题有关,而不是修改后的问题。
问题描述
我的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/