Android App: Address Family not Supported by Protocol - sockets

I am trying to have my Android application sent Telnet commands over a small network to another device, and whenever I declare the DatagramSocket it throws a SocketException saying: Address Family not Supported by Protocol. Here is my code below:
try {
addr = InetAddress.getByName(ipAddress);
sock = new DatagramSocket(); //SocketException created here
//first message - cmd
length = cmd.length();
message = cmd.getBytes();
packet = new DatagramPacket(message, length, addr, portAddr);
sock.send(packet);
//second message - highCMD
length = highCMD.length();
message = highCMD.getBytes();
packet = new DatagramPacket(message, length, addr, portAddr);
sock.send(packet);
sock.close();
} catch (SocketException e) {
AlertDialog alertDialog;
alertDialog = new AlertDialog.Builder(v.getContext()).create();
alertDialog.setTitle("Send High CMD Error!");
alertDialog.setMessage("SocketException");
alertDialog.show();
} catch (IOException e){
AlertDialog alertDialog;
alertDialog = new AlertDialog.Builder(v.getContext()).create();
alertDialog.setTitle("Send High CMD Error!");
alertDialog.setMessage("IOException");
alertDialog.show();
}
}
Possible solutions I've considered but haven't made work:
Emulator needs port redirect through development machine, which ports to use?
I'm not using correct version of IP4/6, how is this set?
Device uses TCP protocol, maybe I'm using the wrong socket type?
Other Important Info:
I've only run this on an Emulator
Development Machine correctly sent telnet commands from Command Prompt
Network consists of development machine, router, and device.
UPDATE: 2/9/11
I've changed this code to the following, but I'm still getting an exception:
try {
addr = InetAddress.getByName(ipAddress);
socketAddress = new InetSocketAddress(addr, portAddr);
sock = new Socket();
sock.connect(socketAddress);
sock.close();
} catch (SocketException e) {
AlertDialog alertDialog;
alertDialog = new AlertDialog.Builder(v.getContext()).create();
alertDialog.setTitle("Send High CMD Error!");
alertDialog.setMessage("SocketException" + e.getMessage());
alertDialog.show();
}
The message from the exception says "Permission Denied." Does this mean that my device is blocking the socket from connecting?

You've coded this the wrong way. Telnet uses TCP which uses stream (connection oriented) sockets, not the datagram sockets used by UDP.
Search for tcp examples.

Related

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.

Why can not I read bytes from the TcpClient in C#?

Why can not I read bytes from the TcpClient in C#?
Here is the error I am getting:
Unable to read data from the transport connection: An established connection was aborted by the software in your host machine.
Here is how I start my TcpClient:
public static async void Start()
{
TcpListener server = null;
try
{
server = new TcpListener(IPAddress.Loopback, 13000);
server.Start();
var client = await server.AcceptTcpClientAsync();
var stream = client.GetStream();
var bytes = Convert.FromBase64String("ABCD");
await stream.WriteAsync(bytes, 0, bytes.Length);
client.Close();
}
catch (Exception e)
{
throw;
}
finally
{
if(server != null)
{
server.Stop();
}
}
}
Here is how I run a request to the TcpClient:
try {
var response = (new HttpClient()).GetByteArrayAsync("http://localhost:13000").Result;
return Convert.ToBase64String(response);
} catch(Exception e) {
throw;
}
The return Convert.ToBase64String(response); line is never reached. While I see the quoted above error message inside the Exception e if I hit a breakpoint on the throw line.
Also, during debug the Start() method completes just fine. I.e. it starts, then wait for a request, gets a request, writes to the TclClient and at the end runs the server.Stop(); command.
I am expecting my code to work, because I took it and modified from the official documentation over here.
I tried to check out a few resources which would tackle my exception, but none of them did help.
E.g. I tried to use the question.
First answer tells nothing useful actually, but just plays around with words and at the end states that one can do nothing about the exception (please, correct me if I am missing a point in the answer).
And the second answer tells an impossible in my case problem. Because, I am sure there is nothing running on the 13000 port.
Your client code is using HttpClient, which sends an HTTP request and expects an HTTP response. But your server is not an HTTP server, it is just a plain TCP server, so the client is likely to fail and forcibly close the connection when it doesn't receive a properly formatted HTTP response.
The "official documentation" whose example you modified is not using HttpClient at all, it is using TcpClient instead.
If you want to use HttpClient in your client, then you should use HttpListener instead of TcpListener in your server.

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?

Xamarin Forms How to change Port or IPAddress of socket connection

I have a UWP (soon to be MacOS also) application that listens for incoming messages. The user can configure which IP Address and Port to listen on. Once the socket connection is listening, the user can also go back into the settings and change the IP Address or Port. I am trying to figure out how to shut down the existing listener and restart it using the new Port / IP Address when the user changes the values. Here is my code that starts the listener. Any help would be appreciated.
private static Socket iobj_listener;
public async static Task StartListening()
{
try
{
Debug.WriteLine("Point 1");
IPEndPoint localEndPoint = new IPEndPoint(ViewModelObjects.AppSettings.ServerIPAddress, ViewModelObjects.AppSettings.ServerPort);
// Create a TCP/IP socket.
iobj_listener = new Socket(ViewModelObjects.AppSettings.ServerIPAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
iobj_listener.Bind(localEndPoint);
iobj_listener.Listen(100);
ViewModelObjects.AppSettings.ListeningOnSocket = true;
while (true)
{
Debug.WriteLine("Point 2");
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
Debug.WriteLine("Waiting for a connection on " + ViewModelObjects.AppSettings.ServerIPAddress.ToString() + "...");
iobj_listener.BeginAccept(
new AsyncCallback(AcceptCallback),
iobj_listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception e)
{
Debug.WriteLine(e.ToString());
}
finally
{
Debug.WriteLine("Point 3");
ViewModelObjects.AppSettings.ListeningOnSocket = false;
}
}
SO I could not find any quick answers so had to kind of figure this out on my own. If you see anything wrong with this, please let me know.
First of all I declared an e_Num as follows
public enum ge_SocketStatus
{
e_NotListening = 0,
e_Listening = 1,
e_Restart = 2
}
Then I added a StopListening function to my class that handles all my Socket communications and set the socket status to not listening as follows:
public static async Task StopListening()
{
try
{
if (iobj_listener.Connected)
{
//Wait till the connection ends or 30 seconds - this is so any last messages can be processed.
await Task.Delay(30000);
}
ViewModelObjects.AppSettings.SocketStatus = ge_SocketStatus.e_NotListening;
iobj_listener.Close(1);
}
catch (Exception ex)
{
App.AppException(ex);
}
}
I then use the value of this enum to know when to end the loop:
public async static Task StartListening()
{
try
{
Debug.WriteLine("Point 1");
IPEndPoint localEndPoint = new IPEndPoint(ViewModelObjects.AppSettings.ServerIPAddress, ViewModelObjects.AppSettings.ServerPort);
// Create a TCP/IP socket.
iobj_listener = new Socket(ViewModelObjects.AppSettings.ServerIPAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
iobj_listener.Bind(localEndPoint);
iobj_listener.Listen(100);
ViewModelObjects.AppSettings.SocketStatus = ge_SocketStatus.e_Listening;
while (ViewModelObjects.AppSettings.SocketStatus == ge_SocketStatus.e_Listening)
{
Debug.WriteLine("Point 2");
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
Debug.WriteLine("Waiting for a connection on " + ViewModelObjects.AppSettings.ServerIPAddress.ToString() + "...");
iobj_listener.BeginAccept(
new AsyncCallback(AcceptCallback),
iobj_listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception e)
{
Debug.WriteLine(e.ToString());
}
finally
{
Debug.WriteLine("Point 3");
}
}
This line above
while (ViewModelObjects.AppSettings.SocketStatus == ge_SocketStatus.e_Listening)
used to be
while (true)
so the loop would never end.
One gotcha I found is in the AcceptCallback used in the BeginAccept function of my socket. In this code, I also had to detect if the socket was connected because this function is called one last time after the StartListening loop exits. At the point the socket is not connected so trying to do anything with is, such as EndAccept, causes the application to throw an exception. Below you can see where I added the line
if (listener.Connected)
in order to stop the code from crashing after I had closed the connection.
public static void AcceptCallback(IAsyncResult ar)
{
// Signal the main thread to continue.
allDone.Set();
// Get the socket that handles the client request.
Socket listener = (Socket)ar.AsyncState;
//If we have shut down the socket don't do this.
if (listener.Connected)
{
Socket handler = listener.EndAccept(ar);
// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
Once all StopListening function ends and everything from the sockets is disconnected, I can call start listening again and open the socket on a different IPAddress and or Port.
I hope this helps as I could not find a good solution to this.

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.