tags:

views:

375

answers:

8

I have some code like this:

InetAddress bind = InetAddress.getByName("192.168.0.1")
MulticastSocket socket = new MulticastSocket(new InetSocketAddress(bind,0));
socket.setInterface(bind);

On windows 7 and windows XP with JDK6u17,I got a SocketException: Socket operation on non socket.

But if I change the line 2 to :

MulticastSocket socket = new MulticastSocket(0);

It's ok, and works find too with jdk6u14.

Why? thanks.

EDIT: Why port 0 should be the matter?

MulticastSocket socket = new MulticastSocket(0);

Everything goes well with this code.But not

MulticastSocket socket = new MulticastSocket(new InetSocketAddress(bind,port));

Whatever the port is.

A: 

According to the documentation, you are supposed to instantiate it with a port number (thus 0 would be valid).

Mark Wilkins
A: 

I am not so sure. What's the constructor MulticastSocket(SocketAddress bindaddr) for. And why it works fine with jdk6u14,but not jdk6u17? And why it ok on windows 2003 server with jdk6u17?

On RHEL5.2 jdk1.4+

http://www.sockets.com/err%5Flst1.htm Berkeley description: An operation was attempted on something that is not a socket. The specified socket parameter refers to a file, not a socket.

WinSock description: Same as Berkeley. The socket input parameter is not a valid socket handle (either it never was valid, it's a file handle (not a socket handle), or if it was a socket handle, it has been closed).

Detailed description:

select(): fails with WSAENOTSOCK if any socket in an fd_set is an invalid socket handle.

Developer suggestions: Did you close a socket inadvertently in one part of an application without keeping another part notified? Use socket state in an application and/or handle this error gracefully as a non-fatal error.

when the MulticastSocket created,socket.isClosed()==true

orzzzzz
A: 

I haven't used these classes before, but the Exception occurs on line 3 when you call the setInterface method.

I would guess it's something to the effect that you're using the same reference twice or something. I found a snippet of code that looked like this, maybe this is how you should be doing it:

    MulticastSocket ms = new MulticastSocket(new InetSocketAddress(0));
    ms.setInterface(InetAddress.getByName("192.168.0.1"));
JRL
MulticastSocket ms = new MulticastSocket(new InetSocketAddress(0));same asMulticastSocket ms = new MulticastSocket(0);
orzzzzz
A: 

I have a feeling that the problem is with your use of port zero. This is a reserved port in UDP and TCP.

EDIT: Assuming that Multicast is interpreting a zero port as meaning that an ephemeral port should be used, what does this actually mean? If your app is going to listen for multicasts, it will need to specify the port on which the multicasts are being sent. OTOH, if your app is going to send multicasts, it needs to use an advertised / well-known port, or else remote apps listening won't know what to listen to.

I suspect that the problem is your use of port zero. In the case where creation of the MulticastSocket "works", I expect that you won't be able to use it.

Stephen C
Multicast use UDP too.port zero means let the System pick up a port.--the problem is:MulticastSocket socket = new MulticastSocket(0); //fine.MulticastSocket socket = new MulticastSocket(new InetSocketAddress(bind,0));//Excpetion.
orzzzzz
Thank you, Stephen C.I want to send multicasts.So far as I know,this port is a local port.Assuming there is a remote app listening on 230.0.0.1:54321.How can I send message to it?A socket on interface 192.168.0.1:<port>. I think the port can be an ephemeral port.
orzzzzz
If there is a remote app listening on 230.0.0.1:54321, you need to be sending on 230.0.0.1:54321. (I take it that 230.0.0.1 is a multicast IP address, not a host IP address.)
Stephen C
how? No local socket descriptor need? Tell the app send the message via 192.168.0.1 at port 12345. 12345 is an ephemeral port.
orzzzzz
Rather than arguing that I'm wrong, why don't you just try using a non-zero port?
Stephen C
Sorry for that.I had tried....
orzzzzz
And ... does a non-zero port work, or does it not work?
Stephen C
See my answer. Port zero isn't 'reserved', it means 'allocate a system-defined port'. Perfectly legal.
EJP
@EJP - sure it is legal ... but listening for multicast on a system defined port isn't very practical. What the OP needs to do is listen for traffic on a port advertised by something else!
Stephen C
Of course, but the OPs's problem is a SocketException: "Socket operation on non-socket". Using port zero doesn't cause those.
EJP
A: 

I had edit the question... port does not the matter.

orzzzzz
A: 

You should first create the Multicast socket with a well known port - something higher than 1024 and less than 65535 - as already stated 0 means the operating system will choose a port for you (but then its going to be kinda random - which I guess you don't want).

For multicast - you generally need to set the interface to use on joinGroup() not on creation - e.g:

MulticastSocket socket = new MulticastSocket(2121);

InetSocketAddress socketAddress = new InetSocketAddress("localhost", 2121);

if (networkInterfaceName != null){
        NetworkInterface ni = NetworkInterface.getByName(networkInterfaceName);
socket.joinGroup(this.socketAddress, ni);

}else {
   socket.joinGroup(socketAddress.getAddress());
}
Rob Davies
You can set the interface at either time, it doesn't matter.
EJP
A: 

According to the MulticastSocket documentation you should use

Class D IP addresses in the range 224.0.0.0 to 239.255.255.255, inclusive

to bind a MulticastSocket. Apparently, the "192.168.0.1" is out of the multicast range.

Lopotun
That's not correct, and it's not what the documentation says. Multicast addresses are specified when joining or leaving groups, and they name the group being joined or left. The bind interface is a local IP address of a local NIC.
EJP
A: 

As you are binding to a specific interface, calling setInterface() to the same interface is redundant. Remove it. It's only needed when you bind to INADDR_ANY, or in Java an InetAddress of null (or unspecified as a parameter).

To address errors in some of the other answers, and their implications:

  1. Port zero is legal. It means a system-assigned port.
  2. You only need a MulticastSocket for receiving multicasts. For sending, you can just use a DatagramSocket.
  3. If the multicast interface needs to be specified, which it doesn't in this case, it can be done either via MulticastSocket.setInterface() or when calling joinGroup() or leaveGroup(). The latter option gives you granularity at the group level, but both techniques work. That's why they're both provided.
  4. If you don't bind to a specific interface you should definitely call setInterface(). If you are on a multi-homed host you must to call joinGroup()/leaveGroup() once per interface, if you want to receive via all of them.

And a question: is 192.168.0.1 an IP address of an NIC on the local machine? It needs to be.

EJP