UWP DatagramsSocket doesn't not fire MessageReceived - sockets

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.

Related

How to receive messages from OSC in Flutter?

I'm trying to receive data from a gadget with OSC Protocol, and with a port that I defined, I can receive the message in the Protokol android app. I want to receive messages in my app. I think the OSCpackage for flutter is not properly working, or maybe I made a wrong!
This is receive function:
int defaultPort = 12345;
void receiveOsc(List<String> args) {
final port = defaultPort;
final socket = OSCSocket(serverPort: port);
print(socket);
socket.listen((msg) {
print("${msg.toString()}");
socket.reply(OSCMessage('/received', arguments: []));
});
}
i Want to get messages in string format in my defined port.

Unity TCP client: connection to a server

I have a hardware that streams data to a windows server, and I have IP and port of this server. Now I want to connect unity app as a TCP client to this server. I have tried many solutions, but still have hard time to figure out best way to do this. Any help is highly appreciated. One issue that I have with current tutorials is that most of them define a unity server and try to connect another unity app as client and mostly based on localhost. However, I just want to connect a unity app as a TCP client to a server which I have IP and port.
Warm regards,
enter image description here
First of all, at the top of your script:
using System;
using System.Net.Sockets;
Then, create an instance of TcpClient and begin the connection:
socket = new TcpClient
{
// dataBufferSize is in bytes
ReceiveBufferSize = dataBufferSize,
SendBufferSize = dataBufferSize
};
socket.BeginConnect(ip, port, ConnectCallback, socket);
In ConnectCallback():
private void ConnectCallback(IAsyncResult asyncResult)
{
socket.EndConnect(asyncResult);
if (!socket.Connected) return;
// stream is a NetworkStream you should declare somewhere
stream = socket.GetStream();
// receiveBuffer is a byte[] you should declare somewhere
receiveBuffer = new byte[dataBufferSize];
stream.BeginRead(receiveBuffer, 0, dataBufferSize, ReceiveCallback, null);
}
In ReceiveCallback():
private void ReceiveCallback(IAsyncResult asyncResult)
{
try
{
int byteLength = stream.EndRead(asyncResult);
if (byteLength <= 0)
{
// Disconnect client
return;
}
// Transfer data from receiveBuffer to data variable for handling
byte[] data = new byte[byteLength];
Array.Copy(receiveBuffer, data, byteLength);
// Handle data in any way you want to
// BeginRead again so you can keep receiving data
stream.BeginRead(receiveBuffer, 0, dataBufferSize, ReceiveCallback, null);
}
catch (Exception e)
{
Console.WriteLine($"Error receiving TCP data: {e.Message}");
}
}
I got this information from this tutorial.

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?

Get pending messages from a Chat

I am developing a chat using quickblox but I am having some problems when I open a new chat. Suddenly I received all the messages that others users sends to me when I was desconnected. The problem is that when I start a chat with user A, I receive the chats from users B, C, D.. in user A chat room.
I have find the way to only show the A users. But the problem is that the server has already sent to me the "disconnected" messages, so when I start a chat to B I do not receive any text because the message that the user B sent to me has been delivered (and ommitted) while I was chating with user A.
How can I do to receive the pending messages (kind of history) or to just retreive the message of the chat I am logged in?
A piece of my code:
// Create Connection.
Connection.DEBUG_ENABLED = true;
config = new ConnectionConfiguration(CHAT_SERVER);
connection = new XMPPConnection(config);
try {
connection.connect();
connection.login(chatLogin, password);
// Create Chat Manager.
chatManager = connection.getChatManager();
// Create Chat.
chat = chatManager.createChat(friendLogin, null);
// // Set listener for outcoming messages.
// chatManager.addChatListener(chatManagerListener);
// Accept only messages from
String from_messages = Integer.toString(receiver_chat_id);
PacketFilter filter = new AndFilter(new PacketTypeFilter(Message.class),
new FromContainsFilter(from_messages+"-3758#chat.quickblox.com"));
// Collect these messages
PacketCollector collector = connection.createPacketCollector(filter);
Packet packet = collector.pollResult();
PacketListener myListener = new PacketListener() {
public void processPacket(Packet packet) {
if (packet instanceof Message) {
Message msg = (Message) packet;
if(msg!=null){
// Process message
System.out.println("Rebem missatge: " +msg.getBody());
}
}
}
};
// Register the listener.
connection.addPacketListener(myListener, filter);
// Set listener for detect Receiver Status
if (connection.isConnected()){
roster = connection.getRoster();
roster.addRosterListener(new RosterListener() {
public void entriesDeleted(Collection<String> addresses) {}
public void entriesUpdated(Collection<String> addresses) {}
public void presenceChanged(Presence presence) {}
public void entriesAdded(Collection<String> arg0) {}
});
}
Make a arraylist and store the receiving offline messages into that array-list. you could add a code in your processPacket(Packet packet) function to add incoming messages to the array-list. or you could use Multimaps(Google Guava) to store all the incoming messages with the key. and when you open the activity that displays the messages from the certain person you could match the name of that person with the key(stored in multimap) and displays the message of that certain person. And the better option is to store all the incomming and outgoing message chat with the certain person so that you could show all the previous chat then you open up the activity.

Design choice for automatically reconnecting socket client

I'm working with a windows form application in C#. I'm using a socket client which is connecting in an asynchronous way to a server. I would like the socket to try reconnecting immediately to the server if the connection is broken for any reason. Which is the best design to approach the problem? Should I build a thread which is continuously checking if the connection is lost and tries to reconnect to the server?
Here is the code of my XcomClient class which is handling the socket communication:
public void StartConnecting()
{
socketClient.BeginConnect(this.remoteEP, new AsyncCallback(ConnectCallback), this.socketClient);
}
private void ConnectCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
// Signal that the connection has been made.
connectDone.Set();
StartReceiving();
NotifyClientStatusSubscribers(true);
}
catch(Exception e)
{
if (!this.socketClient.Connected)
StartConnecting();
else
{
}
}
}
public void StartReceiving()
{
StateObject state = new StateObject();
state.workSocket = this.socketClient;
socketClient.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(OnDataReceived), state);
}
private void OnDataReceived(IAsyncResult ar)
{
try
{
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
// Read data from the remote device.
int iReadBytes = client.EndReceive(ar);
if (iReadBytes > 0)
{
byte[] bytesReceived = new byte[iReadBytes];
Buffer.BlockCopy(state.buffer, 0, bytesReceived, 0, iReadBytes);
this.responseList.Enqueue(bytesReceived);
StartReceiving();
receiveDone.Set();
}
else
{
NotifyClientStatusSubscribers(false);
}
}
catch (SocketException e)
{
NotifyClientStatusSubscribers(false);
}
}
Today I try to catch a disconnection by checking the number of bytes received or catching a socket exception.
If your application only receives data on a socket, then in most cases, you will never detect a broken connection. If you don't receive any data for a long time, you don't know if it's because the connection is broken or if the other end simply hasn't sent any data. You will, of course, detect (as EOF on the socket) connections closed by the other end in the normal fashion despite this.
In order to detect a broken connection, you need a keepalive. You need to either:
make the other end guarantee that it will send data on a set schedule, and you time out and close the connection if you don't get it, or,
send a probe to the other end once in a while. In this case the OS will take care of noticing a broken connection and you will get an error reading the socket if it's broken, either promptly (connection reset by peer) or eventually (connection timed out).
Either way, you need a timer. Whether you implement the timer as an event in an event loop or as a thread that sleeps is up to you and the best solution probably depends on how the rest of your application is structured. If you have a main thread that runs an event loop then it's probably best to hook in to that.
You can also enable the TCP keepalives option on the socket, but an application-layer keepalive is generally considered more robust.