UDP-Client written in Golang fails to receive Message from Server

huangapple go评论83阅读模式
英文:

UDP-Client written in Golang fails to receive Message from Server

问题

你的Go客户端代码存在一些问题。问题可能出在以下几个方面:

  1. 你在Go客户端中使用的IP地址是158.129.239.255,这是Java客户端中使用的广播地址。然而,在Go中,使用广播地址是不被支持的。你需要使用特定的目标IP地址来发送消息。

  2. 在Go客户端中,你使用的是net.DialUDP函数来建立UDP连接。这个函数只能用于发送数据,无法接收数据。所以你需要使用net.ListenUDP函数来监听服务器发送的响应。

  3. 在Go客户端中,你没有正确处理错误。你应该检查err变量并采取相应的错误处理措施。

下面是修改后的Go客户端代码:

package main

import (
	"fmt"
	"log"
	"net"
	"os"
)

func main() {
	service := "127.0.0.1:8888" // 修改为服务器的IP地址和端口号

	// 解析地址
	RemoteAddr, err := net.ResolveUDPAddr("udp", service)
	if err != nil {
		log.Fatal(err)
		os.Exit(1)
	}

	// 建立连接
	conn, err := net.DialUDP("udp", nil, RemoteAddr)
	if err != nil {
		log.Fatal(err)
		os.Exit(1)
	}
	defer conn.Close()

	// 发送消息到服务器
	message := []byte("message")
	_, err = conn.Write(message)
	if err != nil {
		log.Println(err)
	}

	// 接收服务器的响应
	buf := make([]byte, 15000)
	amountByte, remAddr, err := conn.ReadFromUDP(buf)
	if err != nil {
		log.Println(err)
	} else {
		fmt.Println(amountByte, "bytes received from", remAddr)
		fmt.Println("Response:", string(buf[:amountByte]))
	}
}

请注意,你需要将service变量修改为你服务器的IP地址和端口号。另外,你还需要在服务器端运行之后再运行Go客户端,以确保服务器已经在监听状态。

希望这可以帮助到你!如果你还有其他问题,请随时提问。

英文:

I have written a Java Client, which sends a message to the broadcast address.

I have also written a Java Server, which accepts all sent messages and sends the message back to the client.

Now I wanted to try to do exactly the same in Go, just for gaining some experience. The server works fine and is receiving a message and responding to the Java client.

But my Go Client is only sending a message to the Go/Java server but does not receive any message back. According to wireshark the message is sent back to the right IP and Port, but apparently the port is unreachable.

My Code is as follows:
Go Server:

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 Client:

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 Client:

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

What am I doing wrong with my Go Client?

答案1

得分: 10

即使您只打算从连接中发送UDP数据包,通常也应该使用ListenUDP来创建连接,并使用ReadFromUDPWriteToUDP方法。

当您使用DialUDP时,它会创建一个“已连接”的UDP套接字,具有隐式的远程端点,它将过滤传入的数据包。根据Linux的connect手册:

> 如果套接字sockfd的类型为SOCK_DGRAM,则addr是默认发送数据报的地址,也是接收数据报的唯一地址。

英文:

Even if you're you're only going to be sending UDP packets from the connection, you generally want to use ListenUDP to create the connection, and use the ReadFromUDP and WriteToUDP methods.

When you use DialUDP, it creates a "connected" UDP socket, with an implicit remote endpoint, which will filter incoming packets. From the Linux connect man page:

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

答案2

得分: 1

如果你不忽略从WriteToUDP返回的错误,实际上会出现一个错误:"sendto: message too long"。

在OSX上,最大的UDP数据报大小默认设置为9216字节。你尝试发送15000字节。

如果你只想回写接收到的内容,可以写成:

recvBuff[:n]

其中n是接收到的字节数。

英文:

If you don't ignore the error you get back from WriteToUDP it will actually give you an error: "sendto: message to long"

On OSX the the maximum UDP Datagram size is set default to 9216 bytes. You try to send 15000 bytes.

If you just want to write back what you received then write

recvBuff[:n]

, where n is the number of bytes received before.

huangapple
  • 本文由 发表于 2016年3月4日 21:16:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/35797073.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定