Does UDP multicast works with an address other than 0.0.0.0 in VertX 3 - vert.x

Problem 1: It only works when using the 0.0.0.0 address
I'm trying to receive and send multicast messages using Vertx 3.9.2.
I first tried to follow the example in the project's documentation but encountered the NullPointerException problem described in this other SO question. However, I was able to receive multicast messages after specifying a network interface when joining the multicast group.
socket.listen(5001, "0.0.0.0", handler1 -> {
if (handler1.succeeded()) {
socket.listenMulticastGroup("234.3.2.1", "en0", null, handler2 -> {
LOG.debug("Joined multicast group? {}", handler2.succeeded());
socket.handler(packet -> LOG.debug("Received packet: {}", packet));
});
} else {
LOG.error("Failure to listen on address", handler1.cause());
}
});
Nonetheless, receiving multicast messages only works when using the 0.0.0.0 address. I never get multicast messages if I use the address of any of my network interfaces. I first tried like:
socket.listen(5001, "192.168.1.10", handler1 -> {
if (handler1.succeeded()) {
socket.listenMulticastGroup("234.3.2.1", "en0", null, handler2 -> {
LOG.debug("Joined multicast group? {}", handler2.succeeded());
socket.handler(packet -> LOG.debug("Received packet: {}", packet));
});
} else {
LOG.error("Failure to listen on address", handler1.cause());
}
});
And also this other version:
socket.listen(5001, "192.168.1.10", handler1 -> {
if (handler1.succeeded()) {
socket.listenMulticastGroup("234.3.2.1", handler2 -> {
LOG.debug("Joined multicast group? {}", handler2.succeeded());
socket.handler(packet -> LOG.debug("Received packet: {}", packet));
});
} else {
LOG.error("Failure to listen on address", handler1.cause());
}
});
In all three cases the multicast group is successfully joined. But no multicast messages are received with the last two.
Problem 2: Disabling the Loopback mode seems to not work
I'm using the same socket to read and write multicast. When I'm able to receive multicast messages (by binding to 0.0.0.0), I've notice that all the messages written are also received back by the read operation.
This is how the socket is created:
Vertx vertx = Vertx.vertx();
DatagramSocket socket = vertx.createDatagramSocket(
new DatagramSocketOptions()
.setReuseAddress(true)
.setReusePort(true)
.setLoopbackModeDisabled(true)
.setIpV6(false));
One interesting observation is that when binding to another address (like the examples above) I'm able to write multicast messages out and the messages are not "heard back". But I've wonder if the reason is that multicast messages are not received to begin with.
It seems to be a known issue of sorts
I did find an open issue in GitHub that seems to be related to the same problem. It points to a link that's currently broken, but no final resolution is provided.
I truly hope someone can shed some light on the matter.
Update 1
The problem happens in Mac OS X Catalina 10.15.5 and Alpine Linux 3.12 in Docker.
Update 2
Receiving multicast messages also work if you use the multicast address on the listen call.
socket.listen(5001, "234.3.2.1", handler1 -> {
if (handler1.succeeded()) {
socket.listenMulticastGroup("234.3.2.1", "en0", null, handler2 -> {
LOG.debug("Joined multicast group? {}", handler2.succeeded());
socket.handler(packet -> LOG.debug("Received packet: {}", packet));
});
} else {
LOG.error("Failure to listen on address", handler1.cause());
}
});
One cannot write using the socket when calling listen like that however.

Related

Socket IO broadcast to each client with their socket id

I'm getting comfortable with socket.io. It really rocks.
I am aware that from the server, I can either:
Respond to a socket client:
socket.emit(event, data);
Broadcast to other clients:
socket.broadcast.emit(event, data);
Broadcast to all clients without distinction:
io.emit(event, data);
But what I'd like to do is to loop over the clients to emit to each of them, with their socket.id as a parameter:
io.emitEach(socket => socket.emit(event, dataWichDependsOn(socket.id)));
Can I achieve this?
I tried this:
io.of('/').clients((error, clients) => {
if (error) throw error;
return clients.forEach(clientId => {
io.to(clientId).emit(event, dataWichDependsOn(clientId));
})
}
Without success :( the message doesn't seem to be emited.
Object.keys(io.sockets.sockets).forEach((clientId)=>{
io.to(clientId).emit(event, dataWichDependsOn(clientId))
})

UWP - StreamSocket connection error for some connections

We have 2 UWP apps. One app shares data to the other app through StreamSocket. The server app will send data to client app. There will be 30-40 or more devices running the client app and connecting to the server's socket to receive data.
When we test with one client app, all the data sharing happens without any issue. But when we started testing with about 10 devices using the client app, sometimes some apps don't receive data. And there seems to be an error saying A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
In general it get shared to most of the devices, but few fails sometimes randomly. What could be the reason for this? Is there a connection limit to connect to a socket with given IP and port using Stream Socket?
Here is some parts of our code. Please let me know what we have to correct here to avoid getting that error.
Server side
public async Task StartServer(string serverIp, string serverPort)
{
try
{
HostName serverAddress = new HostName(serverIp);
//Create a StreamSocketListener to start listening for TCP connections.
StreamSocketListener socketListener = new StreamSocketListener();
//Hook up an event handler to call when connections are received.
socketListener.ConnectionReceived += SocketListener_ConnectionReceived;
//Start listening for incoming TCP connections on the specified port.
await socketListener.BindEndpointAsync(serverAddress, serverPort);
}
catch (Exception e)
{
}
}
private async void SocketListener_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
try
{
await Task.Run(() => ShareFile(args.Socket));
}
catch (Exception e)
{
}
}
Client side
public async Task ServerConnect(string serverIP, string serverPort)
{
try
{
HostName serverAddress = new HostName(serverIP);
StreamSocket socket = new StreamSocket();
socket.Control.KeepAlive = false;
// Connect to the server.
await socket.ConnectAsync(serverAddress, serverPort, SocketProtectionLevel.PlainSocket);
}
catch (Exception e)
{
}
}
Also would like to get these clarified
-What is the difference between BindServiceNameAsync and BindEndpointAsync? Most examples seems to use the first one. When should we use the second one?
-If we call sender.Dispose(); in SocketListener_ConnectionReceived, will that affect the other clients trying to join the same socket?
-In the ShareFile() function, if we close args.Socket() after sending data, can it close the socket before the client actually read the data from that side?

UWP DatagramsSocket doesn't not fire MessageReceived

I'm working on a UWP application which should communicate via TCP/UDP to a remote device. My issue is that the UWP app successfully sends UDP messages to the remote device, but does not receive the replies.
Here follows the code extracted from the app (simplified):
async Task TestUdpIP()
{
// Writer to the DatagramSocket
DataWriter writer;
using (var udpClient = new DatagramSocket())
{
try
{
// UDP Socket binding
udpClient.MessageReceived += UdpClient_MessageReceived;
var controllerName = new Windows.Networking.HostName(controllerIpAddress.ToString());
await udpClient.BindEndpointAsync(controllerName, controllerIpPort.ToString());
var remoteHostName = new Windows.Networking.HostName(hostIpAddres.ToString());
await udpClient.ConnectAsync(remoteHostName, remoteHostPort.ToString());
// Create a message to send
string message = "Some message";
// Reset the counter of messages received back from the remote robot
messagesReceived = 0;
// Send the message
writer = new DataWriter(udpClient.OutputStream);
writer.WriteString(message);
await writer.StoreAsync();
// Wait for robot status messages
await Task.Delay(5000);
}
catch
{
}
}
}
void UdpClient_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
// Just increment the number of messages received
messagesReceived++;
}
However the UdpClient_MessageReceived handler does not fire. I'm sure that UDP messages are correctly sent from the UWP app and that the remote device replies back as shown in the following screenshot from Wireshark (the test has been taken on the same PC where the UWP app is running)
.
(IP Address, Port) details are shown in the following list to better explain the picture above
UWP application: (192.168.1.108, 19000) to send and receive.
Remote device: (192.168.1.152, 15999) to receive and (192.168.1.152, 54697) to send
Note: this is a similar question, where the answer says that for whatever reason the DatagramSocket should fire some messages before being able to receive. In my example a message is sent out however the message received handler does not fire anyway.
Note: The UWP app has been granted the internet (client) and the internet (client and server) capabilities
Note: I've tried also this (more readable) approach to bind the inbound/outbound datagram socket on the UWP app obtaining the same results:
// UDP Socket binding
var controllerName = new HostName(controllerIpAddress.ToString());
var remoteHostName = new HostName(hostIpAddres.ToString());
EndpointPair endpointpar = new EndpointPair(controllerName,
controllerIpPort.ToString(),
remoteHostName,
remoteHostPort.ToString());
udpClient.MessageReceived += UdpClient_MessageReceived;
await udpClient.ConnectAsync(endpointpar);
Where is the issue? Many thanks!
Please try to also add the Private Networks (Client & Server) capability in your app's manifest.
On other hand, you can try the Official DatagramSocket sample to see whether the both devices can communicate with each other.
After some experimenting, I came out with the idea of using two different DatagramSocket instances: one to send out UDP messages, and one to listen for incoming messages. With this code, I've been able to send UDP messages to the remote device (as before) and also I've been able to receive UDP messages from the remote device.
async Task TestUdpIP_DifferentPorts()
{
// Writer to the DatagramSocket
DataWriter writer;
// Inbound and outbound DatagramSocket
DatagramSocket udpListener = new DatagramSocket();
DatagramSocket udpSender = new DatagramSocket();
try
{
// String containing the serializaed message
string serializedMessage = "Some message";
var controllerName = new HostName(controllerIpAddress.ToString());
var remoteHostName = new HostName(hostIpAddres.ToString());
// Bind listener
udpListener.MessageReceived += UdpClient_MessageReceived;
await udpListener.BindEndpointAsync(controllerName, controllerIpPort.ToString());
// Connect sender
await udpSender.ConnectAsync(remoteHostName, remoteHostPort.ToString());
// Reset the counter of messages received back from the remote robot
messagesReceived = 0;
// Send the message
writer = new DataWriter(udpSender.OutputStream);
writer.WriteString(JsonConvert.SerializeObject(message));
await writer.StoreAsync();
// Wait for robot status messages
await Task.Delay(1000);
}
catch (Exception ex)
{
// Some exception handling
}
udpSender.Dispose();
udpListener.Dispose();
}
void UdpClient_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
// Just increment the number of messages received
messagesReceived++;
}
With this approach only the IP port (or service name) of the inbound listener needs to be specified. The framework will choose the next available outbound IP port.
Note: If I understand well the DatagramSocket.ConnectAsync(EndpointPair) documentation, the same DatagramSocket instance can be used to send and listen for incoming message, so I could not figure out the need for two different instances. From the documentation:
This ConnectAsync(EndPointPair) method on a DatagramSocket is used to define the local and remote endpoint where datagrams will be sent when using the OutputStream property. This method also restricts remote IP addresses of packets that will be accepted to the remote hostname in the endpointPair parameter. Only incoming packets that match the remote endpoint in the endpointPair parameter will trigger the MessageReceived event on the DatagramSocket.

UDP port arduino increment after packet sent

I'm working on a code to communicate two arduinos, one with ethernet shield and another with an ENC28J60 ethernet module. I'm not a newbie in arduino neither an wise/expert yet. But i'm a complete -and less than a- newbie in UDP communication.
Here is the question: my code works fine, it sends and receives UDP packets from one to another and viceversa. But after every packet is sent, it increment in one the "Udp.remotePort" value (that viewing from the "udp-reader" side). It starts from 1024 up to ~32000 (and starts over after reach the highest value). I have researched about UDP and i understand that the first 0-1023 are reserved for specifics services p.e. 80 http, 21 ftp. But i think it should not be incremented after every send. Or it should?
I don't paste the code because as i said it works OK. I just would like to know what could be wrong from your experience.
The sentence i'm using to write the packets is:
udp.beginPacket(IPAddress([ip address]), [port no]);
The libraries i'm using:
UIPEthernet.h https://github.com/UIPEthernet/UIPEthernet for ENC28J60
Ethernet.h for ethernet shield
EDIT: This is the code of the UDP sender (ENC28J60). Basically is the example code of the library as i said it works correctly in terms of communication. I only changed the IPs: 192.168.1.50 which is the UDP sender and 192.168.1.51 which is the UDP destination.
#include <UIPEthernet.h>
EthernetUDP udp;
unsigned long next;
void setup() {
Serial.begin(115200);
uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05};
Ethernet.begin(mac,IPAddress(192,168,1,51));
// Also i used: Ethernet.begin(mac,IPAddress(192,168,1,51), 5000);
// with the same result
next = millis()+2000;
}
void loop() {
int success;
int len = 0;
if (((signed long)(millis()-next))>0)
{
do
{
success = udp.beginPacket(IPAddress(192,168,1,50),5000);
Serial.print("beginPacket: ");
Serial.println(success ? "success" : "failed");
//beginPacket fails if remote ethaddr is unknown. In this case an
//arp-request is send out first and beginPacket succeeds as soon
//the arp-response is received.
}
while (!success && ((signed long)(millis()-next))<0);
if (!success )
goto stop;
success = udp.write("hello world&from&arduino");
Serial.print("bytes written: ");
Serial.println(success);
success = udp.endPacket();
Serial.print("endPacket: ");
Serial.println(success ? "success" : "failed");
do
{
//check for new udp-packet:
success = udp.parsePacket();
}
while (!success && ((signed long)(millis()-next))<0);
if (!success )
goto stop;
Serial.print("received: '");
do
{
int c = udp.read();
Serial.write(c);
len++;
}
while ((success = udp.available())>0);
Serial.print("', ");
Serial.print(len);
Serial.println(" bytes");
//finish reading this packet:
udp.flush();
stop:
udp.stop();
next = millis()+2000;
}
}
EDIT 2: This is a capture of testing with SocketTest listening on port 5000, and after a packet received, the next one arrives with the remote port incremented on 1 each time
You must be creating a new UDP socket per sent datagram. Don't do that. Use the same one for the life of the application.

How to dispatch incoming NetSocket handlers into different event loop threads?

I'm trying to use Vertx to implement a TCP server, accepting incoming connections and then handling different sockets. Since each socket can be handled independently, the handlers belonging to different sockets are supposed to run in different event loop threads concurrently.
According to Vert.x document,
Standard verticles are assigned an event loop thread when they are created and the start method is called with that event loop. When you call any other methods that takes a handler on a core API from an event loop then Vert.x will guarantee that those handlers, when called, will be executed on the same event loop.
I think, this code snippet can print different thread names:
Vertx vertx = Vertx.vertx(); // The number of event loop threads is 2*core.
vertx.createNetServer().connectHandler(socket -> {
vertx.deployVerticle(new AbstractVerticle() {
#Override
public void start() throws Exception {
socket.handler(buffer -> {
log.trace(socket.toString() + ": Socket Message");
socket.close();
});
}
});
}).listen(port);
But unfortunately, all handlers were located in the same thread.
23:59:42.359 [vert.x-eventloop-thread-1] TRACE Server - io.vertx.core.net.impl.NetSocketImpl#253fa4f2: Socket Message
23:59:42.364 [vert.x-eventloop-thread-1] TRACE Server - io.vertx.core.net.impl.NetSocketImpl#465f1533: Socket Message
23:59:42.365 [vert.x-eventloop-thread-1] TRACE Server - io.vertx.core.net.impl.NetSocketImpl#5ab8dac: Socket Message
23:59:42.366 [vert.x-eventloop-thread-1] TRACE Server - io.vertx.core.net.impl.NetSocketImpl#5fc72993: Socket Message
23:59:42.367 [vert.x-eventloop-thread-1] TRACE Server - io.vertx.core.net.impl.NetSocketImpl#38ee66d7: Socket Message
23:59:42.368 [vert.x-eventloop-thread-1] TRACE Server - io.vertx.core.net.impl.NetSocketImpl#6a60a74: Socket Message
23:59:42.369 [vert.x-eventloop-thread-1] TRACE Server - io.vertx.core.net.impl.NetSocketImpl#5f3921e1: Socket Message
23:59:42.370 [vert.x-eventloop-thread-1] TRACE Server - io.vertx.core.net.impl.NetSocketImpl#39d41024: Socket Message
... more than 100+ lines ...
An opposite example is similar to this echo server written in BOOST.ASIO. The handlers run in different event loop threads if a thread pool is used to execute io_service::run().
So, my question is how to run these handlers concurrently?
Actually, you do something entirely different from what you intend.
Each time you receive connection on your socket, you launch a new actor,
Simplest way to prove that:
Vertx vertx = Vertx.vertx(); // The number of event loop threads is 2*core.
vertx.createHttpServer().requestHandler(request -> {
vertx.deployVerticle(new AbstractVerticle() {
String uuid = UUID.randomUUID().toString(); // Some random unique number
#Override
public void start() throws Exception {
request.response().end(uuid + " " + Thread.currentThread().getName());
}
});
}).listen(8888);
vertx.setPeriodic(1000, r -> {
System.out.println(vertx.deploymentIDs().size()); // Print verticles count every second
});
I'm using httpServer just because it's easier to check in browser.
As wrong as it may be, you'll still see that you should receive different threads:
fe931b18-89cc-4c6a-9d6a-8565bb1f1c12 vert.x-eventloop-thread-9
277330da-4df8-4e91-bd8f-82c0f62156d0 vert.x-eventloop-thread-11
bbd3207c-80a4-41d8-9be5-b40727badc84 vert.x-eventloop-thread-13
Now to how you should do it:
// We create 10 workers
for (int i = 0; i < 10; i++) {
vertx.deployVerticle(new AbstractVerticle() {
#Override
public void start() {
vertx.eventBus().consumer("processMessage", (request) -> {
// Do something smart
// Reply
request.reply("I'm on thread " + Thread.currentThread().getName());
});
}
});
}
// This is your handler
vertx.createHttpServer().requestHandler(request -> {
// Only one server, that should dispatch events to workers as quickly as possible
vertx.eventBus().send("processMessage", null, (response) -> {
if (response.succeeded()) {
request.response().end("Request :" + response.result().body().toString());
}
// Handle errors
});
}).listen(8888);
vertx.setPeriodic(1000, r -> {
System.out.println(vertx.deploymentIDs().size()); // Notice that number of workers doesn't change
});
It's not possible to determine which event loop Vert.x will assign to each of your verticles without more details (number of cores of your test machines for example).
Anyway, it is not a good idea to deploy a verticle per incoming connection. Verticles are units of deployment in Vert.x. You would typically create one per "functionality".
Back to your use case, the purpose of event driven programming is precisely to avoid using a thread per connection. You can handle a lot of concurrent connections with a single event loop. If you have multiple cores on your machine then you can deploy multiple instances of your verticle to use them all (1 event loop per core).
int processors = Runtime.getRuntime().availableProcessors();
Vertx vertx = Vertx.vertx();
vertx.deployVerticle(TCPServerVerticle.class.getName(), new DeploymentOptions().setInstances(processors));
public class TCPServerVerticle extends AbstractVerticle {
#Override
public void start(Future<Void> startFuture) throws Exception {
vertx.createNetServer().connectHandler(socket -> {
socket.handler(buffer -> {
log.trace(socket.toString() + ": Socket Message");
socket.close();
});
}).listen(port, ar -> {
if (ar.succeeded()) {
startFuture.complete();
} else {
startFuture.fail(ar.cause());
}
});
}
}
With Vertx TCP server sharing the connect handlers will be called on a round-robin fashion.