Golang 写的 UDP-Client 无法接收来自服务器的消息
UDP-Client written in Golang fails to receive Message from Server
我写了一个Java客户端,它向广播地址发送消息。
我也写了一个Java服务器,它接受所有发送的消息并将消息发送回客户端。
现在我想尝试在 Go 中做完全相同的事情,只是为了获得一些经验。服务器工作正常,正在接收消息并响应 Java 客户端。
但是我的 Go 客户端只向 Go/Java 服务器发送消息,但没有收到任何返回消息。根据 wireshark,消息被发送回正确的 IP 和端口,但显然该端口无法访问。
我的代码如下:
围棋服务器:
package main
import (
"fmt"
"log"
"net"
)
func main() {
//Resolving address
udpAddr, err := net.ResolveUDPAddr("udp4", "0.0.0.0:8888")
if err != nil {
log.Println("Error: ", err)
}
// Build listining connections
conn, err := net.ListenUDP("udp", udpAddr)
defer conn.Close()
if err != nil {
log.Println("Error: ", err)
}
// Interacting with one client at a time
for {
fmt.Println(">>>Ready to receive broadcast packets!")
// Receiving a message
recvBuff := make([]byte, 15000)
_, rmAddr, err := conn.ReadFromUDP(recvBuff)
if err != nil {
panic(err)
}
fmt.Println(">>>Discovery packet received from: " + rmAddr.String())
fmt.Println(">>>Packet received; data: " + string(recvBuff))
// Sending the same message back to current client
conn.WriteToUDP(recvBuff, rmAddr)
fmt.Println(">>>Sent packet to: " + rmAddr.String())
}
}
Go 客户端:
package main
import (
"fmt"
"log"
"net"
"os"
)
func main() {
service := "158.129.239.255:8888"
// Resolving Address
RemoteAddr, err := net.ResolveUDPAddr("udp", service)
// Make a connection
conn, err := net.DialUDP("udp", nil, RemoteAddr)
defer conn.Close()
// Exit if some error occured
if err != nil {
log.Fatal(err)
os.Exit(1)
}
// write a message to server
message := []byte("message")
_, err = conn.Write(message)
fmt.Println(">>> Request packet sent to: 158.129.239.255 (DEFAULT)")
if err != nil {
log.Println(err)
}
// Receive response from server
buf := make([]byte, 15000)
amountByte, remAddr, err := conn.ReadFromUDP(buf)
if err != nil {
log.Println(err)
} else {
fmt.Println(amountByte, "bytes received from", remAddr)
}
}
Java 客户:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
import java.util.logging.Level;
import java.util.logging.Logger;
public class BroadcastUDPClient {
public static void main(String[] args) {
// Find the server using UDP broadcast
try {
//Open a random port to send the package
DatagramSocket sendSD = new DatagramSocket();
sendSD.setBroadcast(true);
byte[] sendData = "message".getBytes();
//Try the 255.255.255.255 first
try {
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getByName("158.129.239.255"), 8888);
sendSD.send(sendPacket);
System.out.println(">>> Request packet sent to: 158.129.239.255 (DEFAULT)");
} catch (Exception e) {
}
//Wait for a response
byte[] recvBuf = new byte[15000];
DatagramPacket receivePacket = new DatagramPacket(recvBuf, recvBuf.length);
sendSD.receive(receivePacket);
//We have a response
System.out.println(">>> Broadcast response from server: " + receivePacket.getAddress().getHostAddress());
String message = new String(receivePacket.getData()).trim();
System.out.println(">>> Message Body: " + message);
//Close the port!
sendSD.close();
} catch (IOException ex) {
Logger.getLogger(BroadcastUDPClient.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
我的 Go 客户端有什么问题?
如果您不忽略从 WriteToUDP 返回的错误,它实际上会给您一个错误:"sendto: message to long"
在 OSX 上,最大 UDP 数据报大小默认设置为 9216 字节。您尝试发送 15000 个字节。
如果您只想写回收到的内容,请写
recvBuff[:n]
,其中n是之前接收到的字节数。
即使您只打算从连接发送 UDP 数据包,您通常也希望使用 ListenUDP
来创建连接,并使用 ReadFromUDP
和 WriteToUDP
方法。
当您使用 DialUDP
时,它会创建一个 "connected" UDP 套接字,带有一个隐式远程端点,它将过滤传入的数据包。来自 Linux connect
手册页:
If the socket sockfd is of type SOCK_DGRAM then addr is the address to which datagrams are sent by default, and the only address from which datagrams are received.
我写了一个Java客户端,它向广播地址发送消息。
我也写了一个Java服务器,它接受所有发送的消息并将消息发送回客户端。
现在我想尝试在 Go 中做完全相同的事情,只是为了获得一些经验。服务器工作正常,正在接收消息并响应 Java 客户端。
但是我的 Go 客户端只向 Go/Java 服务器发送消息,但没有收到任何返回消息。根据 wireshark,消息被发送回正确的 IP 和端口,但显然该端口无法访问。
我的代码如下: 围棋服务器:
package main
import (
"fmt"
"log"
"net"
)
func main() {
//Resolving address
udpAddr, err := net.ResolveUDPAddr("udp4", "0.0.0.0:8888")
if err != nil {
log.Println("Error: ", err)
}
// Build listining connections
conn, err := net.ListenUDP("udp", udpAddr)
defer conn.Close()
if err != nil {
log.Println("Error: ", err)
}
// Interacting with one client at a time
for {
fmt.Println(">>>Ready to receive broadcast packets!")
// Receiving a message
recvBuff := make([]byte, 15000)
_, rmAddr, err := conn.ReadFromUDP(recvBuff)
if err != nil {
panic(err)
}
fmt.Println(">>>Discovery packet received from: " + rmAddr.String())
fmt.Println(">>>Packet received; data: " + string(recvBuff))
// Sending the same message back to current client
conn.WriteToUDP(recvBuff, rmAddr)
fmt.Println(">>>Sent packet to: " + rmAddr.String())
} }
Go 客户端:
package main
import (
"fmt"
"log"
"net"
"os"
)
func main() {
service := "158.129.239.255:8888"
// Resolving Address
RemoteAddr, err := net.ResolveUDPAddr("udp", service)
// Make a connection
conn, err := net.DialUDP("udp", nil, RemoteAddr)
defer conn.Close()
// Exit if some error occured
if err != nil {
log.Fatal(err)
os.Exit(1)
}
// write a message to server
message := []byte("message")
_, err = conn.Write(message)
fmt.Println(">>> Request packet sent to: 158.129.239.255 (DEFAULT)")
if err != nil {
log.Println(err)
}
// Receive response from server
buf := make([]byte, 15000)
amountByte, remAddr, err := conn.ReadFromUDP(buf)
if err != nil {
log.Println(err)
} else {
fmt.Println(amountByte, "bytes received from", remAddr)
}
}
Java 客户:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
import java.util.logging.Level;
import java.util.logging.Logger;
public class BroadcastUDPClient {
public static void main(String[] args) {
// Find the server using UDP broadcast
try {
//Open a random port to send the package
DatagramSocket sendSD = new DatagramSocket();
sendSD.setBroadcast(true);
byte[] sendData = "message".getBytes();
//Try the 255.255.255.255 first
try {
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getByName("158.129.239.255"), 8888);
sendSD.send(sendPacket);
System.out.println(">>> Request packet sent to: 158.129.239.255 (DEFAULT)");
} catch (Exception e) {
}
//Wait for a response
byte[] recvBuf = new byte[15000];
DatagramPacket receivePacket = new DatagramPacket(recvBuf, recvBuf.length);
sendSD.receive(receivePacket);
//We have a response
System.out.println(">>> Broadcast response from server: " + receivePacket.getAddress().getHostAddress());
String message = new String(receivePacket.getData()).trim();
System.out.println(">>> Message Body: " + message);
//Close the port!
sendSD.close();
} catch (IOException ex) {
Logger.getLogger(BroadcastUDPClient.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
我的 Go 客户端有什么问题?
如果您不忽略从 WriteToUDP 返回的错误,它实际上会给您一个错误:"sendto: message to long"
在 OSX 上,最大 UDP 数据报大小默认设置为 9216 字节。您尝试发送 15000 个字节。
如果您只想写回收到的内容,请写
recvBuff[:n]
,其中n是之前接收到的字节数。
即使您只打算从连接发送 UDP 数据包,您通常也希望使用 ListenUDP
来创建连接,并使用 ReadFromUDP
和 WriteToUDP
方法。
当您使用 DialUDP
时,它会创建一个 "connected" UDP 套接字,带有一个隐式远程端点,它将过滤传入的数据包。来自 Linux connect
手册页:
If the socket sockfd is of type SOCK_DGRAM then addr is the address to which datagrams are sent by default, and the only address from which datagrams are received.