0

It's weird that I use WireShark to test the result, and the result shows that my code can successfully send messages via socket. But my program will throw a Timeout exception even if I receive the message from the server.
I don't know why there is a timeout problem.

My code is simple:

static Timer timer = new Timer();
try {
    DatagramSocket c = new DatagramSocket();

    c.setBroadcast(true);

    byte[] sendData = "messageToServer".getBytes();
    try {
        DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getByName("255.255.255.255"), 10000);
        c.connect(InetAddress.getByName("255.255.255.255"), 10000);
        c.send(sendPacket);
    } catch(Exception ex) {
        System.out.println(ex.toString());
    }
    timer.schedule(new receiveTask(), 2000);
} catch(Exception ex) {
    System.out.println(ex.toString());
}

I use a timer to delay the reception of the message from the server.

The receiveTask class looks like this:

public class receiveTask  extends TimerTask {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        try {
            DatagramSocket c2 = new DatagramSocket();
            c2.setSoTimeout(10000);
            byte[] recvBuf = new byte[1024];
            DatagramPacket receivePacket = new DatagramPacket(recvBuf, recvBuf.length);
            String message = "";
            while (true) {
                c2.receive(receivePacket);
                System.out.println("Receive packet from Server");
                message=new String(receivePacket.getData()).trim();
                System.out.println(message);
                System.out.println("Close the connection of server socket");
            }
        } catch(Exception ex) {
            System.out.println(ex.toString());
        }
    }
}

And a SocketTimeOut exception is thrown in the receiveTask class.

Since the server can send a message to me (tested in WireShark), I don't think the fult is server-side. But what can cause the time-out?

Why the server returns a message to me but I can't receive it in my program?

My Java version is 7, and it makes no difference disabling the firewall on my computer...

Any advice will be appreciated!

Edit: Though the problem isn't about socket.close(); I remvoe the code.

Shuinvy
  • 251
  • 2
  • 6
  • 23
  • You're sending a message to port 10000, but you're not receiving on port 10000. You're closing the socket after the first successful receive and then trying another one. This doesn't make much sense. – user207421 Aug 29 '14 at 04:43

2 Answers2

1

There are a few things you can try.

First of all, try invoke timer.schedule(new receiveTask(), 2000); earlier so that your receiveTask is ready to receive messages before any are sent.

Secondly, move your c.close() statement to a finally clause, especially the one inside the while loop of receiveTask to ensure your sockets don't get closed prematurely. So the codes will look like

DatagramSocket c2 = null;
try{
    c2 = new DatagramSocket();
    c2.setSoTimeout(10000);
    byte[] recvBuf = new byte[1024];
    DatagramPacket receivePacket = new DatagramPacket(recvBuf, recvBuf.length);
    String message = "";
    while(true){            
        c2.receive(receivePacket);
        System.out.println("Receive packet from Server");
        message=new String(receivePacket.getData()).trim();
        System.out.println(message);                
        System.out.println("Close the connection of server socket");
    }
}catch(Exception ex){
    System.out.println(ex.toString());
} finally{
    if(c2 != null)
        c2.close();
}

If all else failed, try c2.setSoTimeout(0); which will cause the timeout to be set to infinite. But I have a feeling this is only a hack to mask the real problem.

ivan.sim
  • 8,972
  • 8
  • 47
  • 63
  • Thanks for your advice! Even try other's code:as [link](http://stackoverflow.com/questions/6579350/sending-packets-to-255-255-255-255-by-java-datagramsocket-fails), it still doesn't work. Maybe it is the problem of my computer? But I try doing it in C#, and it works fine......( but C# needs to install .Net framework, that's the reason why I use java instead, because some people use XP and don't have .Net framework) – Shuinvy Aug 29 '14 at 01:19
  • @Shuinvy Try change your broadcast address from `255.255.255.255` to `192.168.1.255` as per the answer to [this question](http://stackoverflow.com/q/2950715/1144203). You might also have to use [`MulticastSocket`](http://docs.oracle.com/javase/tutorial/networking/datagrams/broadcasting.html) instead of `DatagramSocket`. – ivan.sim Aug 29 '14 at 02:51
0

Thanks for everyone's help! I ask my coworker, and I should do another way: open my own server part to receive the returned messages.

I have heard from others that java may not receive return messages appropriately( maybe that's the reason why I always time out!), since the sending part is okay, just open a server part about listening packages, and I can receive the messages from the server I want, too!

Be aware, you should use the same port of the target server, so you will get your own package that you sent, too. Just filter the sending address of your program.

The server side and full concept is like this:

    static DatagramSocket socket2;
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        // Open my own server part to listen messages from broadcast returned
        listen();
        // Sending UDP broadcast in this part as question implied
    }
    public static void listen() {
        new Thread() {
            public void run() {
                try{
                    socket2 = new DatagramSocket(10000);
                    socket2.setBroadcast(true);
                    byte[] recvBuf = new byte[1024];

                    while (true) {
                        DatagramPacket packet2 = new DatagramPacket(recvBuf, recvBuf.length);
                        try{
                            socket2.receive(packet2);
                            System.out.println("Discovery packet received from: " + packet2.getAddress().getHostAddress());
                            System.out.println("Packet received; data: " + new String(packet2.getData()));
                            String message = new String(packet2.getData());
                            System.out.println("Received: "+message);

                        }catch(Exception ex){
                            System.out.println("Cannot receive package: " + ex.getMessage());
                        }
                    }
                }catch(Exception ex){
                    socket2.close();
                    System.out.println("Server side problem occured: " + ex.getMessage());
                }
            }
        }.start();
    }

Though you may notice the code is similar, but the concept is different.

And finding what's the problem is better than just find the method to solve problem, I think!

If my opinion is wrong, hope someone can correct it.

Shuinvy
  • 251
  • 2
  • 6
  • 23