|
A
MulticastSocket
is the Yoix representation of Java's MulticastSocket class that can be used
to join multicast groups and to
send
and
receive
multicast UDP (User Datagram Protocol) packets.
We have had mixed results using
MulticastSockets
and have not had time to really track the problems down.
The Linux systems that we used for testing behaved poorly,
while OSX and Windows did much better.
The problems that we encountered could be mistakes in our Java code,
however some long-standing bugs summarized in the 4701650 Java bug report
seem to describe our experience.
We plan on more testing and debugging, but until then you probably should
suspect low level Java or Yoix interpreter bugs if you have trouble using
MulticastSockets,
particularly on Linux systems.
The fields in a
MulticastSocket
are:
| alive |
An
int
that is
1
if the multicastsocket has been activated and
0
otherwise.
Storing
1
in
alive
activates the multicastsocket, which automatically tries to bind it to
localaddress
and
localport
and then connect it to
remoteaddress
and
remoteport.
Calling the
send
or
receive
built-ins also activate the multicastsocket.
Storing
0
in
alive
closes the multicastsocket, which means it is no longer bound to a local address
or connected to a remote system.
| | broadcast |
An
int
that is
1
if the multicastsocket can send broadcast datagrams and
0
if it can not.
Storing a negative number in
broadcast
is ignored and makes no changes to the current setting.
| | joinGroup(String address) |
A
Builtin
that tries to join the multicast group
address,
which should be a IP address in the range
224.0.0.0
to
239.255.255.255
or a name that can be resolved by DNS to an IP address in that range,
and returns
1
if the group was successfully joined and
0
if it was not.
Groups that we successfully join are also added to the
joinedgroups
array.
Addresses
224.0.0.0
through
224.0.0.255
are reserved for local administrative purposes.
For example, ping
224.0.0.1,
which is the group that every multicast capable host joins when it starts up,
and all hosts in that group should answer.
Addresses
239.0.0.0
through
239.255.255.255
are reserved for administrative scoping.
| | joinedgroups |
An
Array
that lists the multicast groups that this mulitcastsocket currently belongs to, or
NULL
if the list of groups is empty.
| | leaveGroup(String address) |
A
Builtin
that tries to leave the multicast group
address,
which should be a IP address in the range
224.0.0.0
to
239.255.255.255
or a name that can be resolved by DNS to an IP address in that range,
and returns
1
if the group was successfully left and
0
if it was not.
Groups that we successfully leave are removed from the
joinedgroups
array.
| | localaddress |
A
String
that identifies network interfaces on the local machine
that the multicastsocket will bind to when it is activated.
localaddress
is currently a read-only field, which means the multicastsocket always
binds to the wildcard address that usually matches any local address.
Changing
localaddress
is not allowed and will result in an
invalidaccess
error.
This was done in response to Java bug report 4701650, which states that
binding to a specific address can result in "wildly platform specific behavior".
| | localname |
A read-only
String
that is the name of the host associated with the IP address read from
localaddress
when the multicastsocket is
alive
and
NULL
when it is not
alive.
| | localport |
An
int
that identifies the port that the multicastsocket will bind to when it is activated.
The value should be an integer between
0
(the default) and
65535,
inclusive.
A
localport
that is
0
means the system should pick an ephemeral port.
A multicastsocket that is bound to
localaddress
and
localport
will only receive packets directed to that address and port.
Changing
localport
while a multicastsocket is
alive
is not allowed and will result in an
invalidaccess
error.
| | loopback |
An
int
that is
1
(the default) if packets sent by this multicastsocket to a group that it joined
should be looped back for local delivery to this multicastsocket, and
0
if they should not.
In other words, setting
loopbackmode
to
0
means this multicastsocket does not want to receive the data that it sends
a multicast group.
Storing a negative number in
loopbackmode
is ignored and makes no changes to the current setting.
Some of the simple tests that we ran on Windows and OSX seemed to misbehave when
0
was stored in
loopbackmode,
which is why the default mode is enabled.
| | networkinterface |
A
String
that should be the name of the network interface
(e.g.,
eth0
or
lo),
that should be used for multicast packets that are sent by this multicastsocket.
| | receive(String buf [, Pointer addr, Pointer port]) |
A
Builtin
that waits for a datagram packet to arrive at this multicastsocket's
localaddress
and
localport,
stores the packet data in
buf,
and returns the number of bytes received or
-1
if
receive
timed out, was interrupted, or encountered any other kind of error.
receive
automatically activates the multicastsocket if it is not
alive.
The string buffer
buf
must be large enough to accommodate the data in any expected packet;
bytes that don't fit will be lost.
Information about where the data came from can stored in the locations
that the optional
addr
and
port
arguments point to.
addr
should point to a string that will be filled in with the IP address
of the host that sent the data.
port
should point to an integer that will be filled in with a port that
can be used to contact the host that sent the data.
A multicastsocket that is connected to
remoteaddress
and
remoteport
can only receive packets from that address and port, which means the optional
addr
and
port
arguments will not provide any additional information.
| | receivebuffersize |
An
int
that is the size, in bytes, of the buffer used by the multicastsocket
to receive packets.
Reading returns the actual buffer size if the multicastsocket is
alive,
or the size that will be requested from the operating system
when it is activated.
Writing requests a buffer of a certain size, however the request may or may
not be honored by the operating system.
Storing a negative number in
receivebuffersize
is ignored and makes no changes to the current setting.
| | remoteaddress |
A
String
that identifies a remote system that the multicastsocket should be connected
to when it is
alive.
The value should be an IP address, a name that can be resolved by DNS, or
NULL
(the default) which means the multicastsocket is not connected.
A multicastsocket that is
alive
and connected to
remoteaddress
and
remoteport
can only
send
packets to or
receive
packets from that address and port.
A multicastsocket that is
alive
and has a
NULL
remoteaddress
or a
remoteport
that is
-1
is not connected to a remote system.
Reading
remoteaddress
when the multicastsocket is
alive
always returns the IP address or
NULL.
Writing first disconnects the multicastsocket and then tries to establish
a new connection when
remoteaddress
is not
NULL
and
remoteport
is integer between
0
and
65535,
inclusive.
| | remotename |
A read-only
String
that is the name of the host associated with the IP address read from
remoteaddress
or
NULL
when the multicastsocket is not
alive
or not connected to a remote system.
| | remoteport |
An
int
that identifies the port on
remoteaddress
that the multicastsocket should be connected to when it is
alive.
A multicastsocket that is
alive
and connected to
remoteaddress
and
remoteport
can only
send
packets to or
receive
packets from that address and port.
A multicastsocket that is
alive
and has a
NULL
remoteaddress
or a
remoteport
that is
-1
is not connected to a remote system.
Writing first disconnects the multicastsocket and then tries to establish
a new connection when
remoteport
is integer between
0
and
65535,
inclusive and
remoteaddress
is not
NULL.
| | reuseaddress |
An
int
that is
1
if more than one multicastsocket can be bound to the same
localaddress
and
localport
pair and
0
otherwise.
Storing a negative number in
reuseaddress
is ignored and makes no changes to the current setting.
| | send(String buf [, String addr, int port]) |
A
Builtin
that uses this multicastsocket to send the contents of
buf
to a remote system and returns the number of bytes sent or
-1
if there was an error.
Nothing is sent and
0
is returned if
buf
is
NULL
or the empty string (i.e.,
"").
send
automatically activates the multicastsocket if it is not
alive.
A multicastsocket that is connected to
remoteaddress
and
remoteport
can only send packets to that address and port, which means the optional
addr
and
port
arguments should be omitted.
A multicastsocket that is not connected to a remote system must be told where
buf
should go using the
addr
and
port
arguments.
addr
should be an IP address, a name that can be resolved by DNS, or
NULL
which is a convenient way to refer to the local host.
port
should be an integer between 0 to 65535, inclusive.
| | sendbuffersize |
An
int
that is the size, in bytes, of the network buffers used by the multicastsocket
to send packets.
Reading returns the actual size if the multicastsocket is
alive,
or the size that will be requested from the operating system
when it is activated.
Writing requests buffers of a certain size, however the request may or may
not be honored by the operating system.
Storing a negative number in
sendbuffersize
is ignored and makes no changes to the current setting.
| | timeout |
A
double
that specifies how long the
receive
built-in will wait, in seconds, before giving up.
A zero value disables timeouts and means
receive
will wait forever.
Writing is allowed, but does not affect a
receive
call that has already started.
Storing a negative number in
timeout
is ignored and makes no changes to the current setting.
| | timetolive |
An
int
between
0
and
255
that is used as the time-to-live for multicast packets that are sent
by this multicastsocket.
When a packet passes through a router its time-to-live is decremented
and when it gets to
0
it will not be transmitted.
Setting
timetolive
to
1
means multicast packets will only be transmitted on the local network.
A value greater that
1
means mulitcast packets may be forwarded to other networks, while
0
means multicast packets will not be transmitted on any network.
Storing a negative number in
timetolive
is ignored and makes no changes to the current setting.
| | trafficclass |
An
int
that requests a type-of-service and precedence, using constants defined in
yoix.net,
for datagrams that are sent from the multicastsocket.
The type-of-service should be one of
IPTOS_LOWCOST,
IPTOS_LOWDELAY,
IPTOS_RELIABILITY,
IPTOS_THROUGHPUT,
or
IPTOS_NORMAL
(the default),
while the precedence should be one of
IPPREC_0
(the default),
IPPREC_1,
IPPREC_2,
IPPREC_3,
IPPREC_4,
IPPREC_5,
IPPREC_6,
or
IPPREC_7.
The type-of-service and precedence can be combined using a bitwise-or operation
and the result can be stored in
trafficclass.
Storing a negative number in
trafficclass
is ignored and makes no changes to the current setting.
Two other constants defined in
yoix.net,
namely
IPTOS_MASK
and
IPPREC_MASK,
can be used to extract the type-of-service and precedence from the value
obtained when the
trafficclass
field is read.
|
Several permanent fields have not been documented and should not be
used in Yoix applications.
If you look closely you may notice that many fields in a
MulticastSocket
are initialized with values, like
-1,
that the documentation says are explicitly ignored.
It is an approach that lets Java (and your operating system) pick values
when the multicastsocket is activated for fields that you choose not to initialize.
| |
| Example: |
The program
import yoix.*.*;
MulticastSocket socket;
String buf[100];
String address;
String name;
String message;
String group;
int counter = 1;
int port;
int count;
int n;
if (argc == 2 || argc == 3) {
if (isMulticastAddress(argv[1])) {
socket.localport = 6789;
socket.joinGroup(argv[1]);
name = (argc == 3) ? argv[2] : "unknown";
} else fprintf(stderr, "invalid address\n", argv[1]);
} else fprintf(stderr, "usage error\n");
if (socket.joinedgroups != NULL) {
socket.timeout = 1;
socket.timetolive = 1;
group = socket.joinedgroups[0];
for (n = 0; n < 20; n++) {
message = strfmt("message %d from %s", counter++, name);
count = socket.send(message, group, socket.localport);
printf(" sent: count=%d bytes to %s:%d\n",
count, group, socket.localport);
sleep(2);
while (socket.receive(buf, &address, &port) > 0)
printf("received: %s from %s:%d\n", buf, address, port);
sleep(2);
}
}
is a simple
MulitcastSocket
test that currently only sends packets out on your local network
(because
timetolive
is set to
1).
Type something like,
yoix multicasttest.yx 228.5.6.7 john
to start sending messages to multicast group 228.5.6.7 as "john",
yoix multicasttest.yx 228.5.6.7 rich
to start sending messages to the same group as "rich",
and both should start receiving all the messages that are sent to the group.
Unfortunately we have had some problems with
MulitcastSockets,
particularly on Linux, so you may not have much luck running this script.
| | |
| See Also: |
DatagramSocket,
getAddress,
getAllByName,
getHostAddress,
getHostName,
getInterfaceAddress,
getInterfaceAddresses,
isAnyLocalAddress,
isLinkLocalAddress,
isLoopbackAddress,
isMulticastAddress,
isSiteLocalAddress,
ServerSocket,
Socket
|
|