2014-09-25 91 views
7

我正在寻找一种在Go语言中使用UDP套接字进行客户端/服务器通信的良好解决方案。在Go中写入客户端UDP套接字

我在互联网上找到的例子告诉我如何发送数据到服务器,但他们没有教会如何将它们发送回客户端。

为了证明,我的程序执行以下操作:

我的客户端程序的4444端口上创建了一个插座,就像这样:

con, err := net.Dial("udp", "127.0.0.1:4444") 

我发送一个字符串和本地地址的服务器,所以它可以打印字符串并发送OK消息。我使用的采空此:

enc := gob.NewEncoder(con) 
enc.Encode(Data{"test", con.LocalAddr().String()}) 

我的数据结构是这样的:

type Data struct{ 
    Msg string 
    Addr string 
} 

我的服务器监听4444端口,并正确地解码的采空区,但我怎么能发送OK消息返回?我使用的客户端地址这样做(在服务器上。去文件):

con, err := net.Dial("udp", data.Addr) 

然后,我得到一个错误代码:

write udp 127.0.0.1:35290: connection refused 

当客户端试图连接到服务器的端口4444,客户端创建一个带有随机数的端口(在本例中为35290),以便它们可以进行通信。我知道我不应该将客户端的地址传递给服务器,但是conn.RemoteAddress()不起作用。一个解决方案,发现客户的地址将不胜感激。

Obs .:我知道里面有ReadFromUDP,所以我可以看包。我应该阅读它,发现客户的地址,并将数据发送给GOB,以便它可以解码它?

+1

读取的数据包。使用从ReadFromUDP返回的地址使用[WriteToUDP](http://godoc.org/net#UDPConn.WriteToUDP)进行回复。 – 2014-09-25 02:38:16

+0

我在想那个,但Gob会如何适应这种情况呢? – Aleksandrus 2014-09-25 14:27:45

+2

使用'var b bytes.Buffer; err:= gob.NewEncoder(&b).Encode(v)'并将b.Bytes()写入连接。使用'err:= gob.NewDecoder(bytes.NewReader(p))解码gobs。解码(&v)'其中p是从连接读取的数据。 – 2014-09-25 14:33:07

回答

14

检查以下示例以了解UDP上的客户端/服务器通信。 sendResponse例程用于将响应发送回客户端。使用[ReadFromUDP](http://godoc.org/net#UDPConn.ReadFromUDP)

udpclient.go

package main 
import (
    "fmt" 
    "net" 
    "bufio" 
) 

func main() { 
    p := make([]byte, 2048) 
    conn, err := net.Dial("udp", "127.0.0.1:1234") 
    if err != nil { 
     fmt.Printf("Some error %v", err) 
     return 
    } 
    fmt.Fprintf(conn, "Hi UDP Server, How are you doing?") 
    _, err = bufio.NewReader(conn).Read(p) 
    if err == nil { 
     fmt.Printf("%s\n", p) 
    } else { 
     fmt.Printf("Some error %v\n", err) 
    } 
    conn.Close() 
} 

udpserver.go

package main 
import (
    "fmt" 
    "net" 
) 


func sendResponse(conn *net.UDPConn, addr *net.UDPAddr) { 
    _,err := conn.WriteToUDP([]byte("From server: Hello I got your mesage "), addr) 
    if err != nil { 
     fmt.Printf("Couldn't send response %v", err) 
    } 
} 


func main() { 
    p := make([]byte, 2048) 
    addr := net.UDPAddr{ 
     Port: 1234, 
     IP: net.ParseIP("127.0.0.1"), 
    } 
    ser, err := net.ListenUDP("udp", &addr) 
    if err != nil { 
     fmt.Printf("Some error %v\n", err) 
     return 
    } 
    for { 
     _,remoteaddr,err := ser.ReadFromUDP(p) 
     fmt.Printf("Read a message from %v %s \n", remoteaddr, p) 
     if err != nil { 
      fmt.Printf("Some error %v", err) 
      continue 
     } 
     go sendResponse(ser, remoteaddr) 
    } 
} 
+0

udpclient.go中的conn.Close()行最好放置一个被动句子,如:defer conn.Close() – alsotoes 2017-10-31 07:46:36