Interprocess communication between Android and C# - c#

Attempting to perform sockets communication between Android and C# I seem to be stuck.
This is basically the code I have so far.
Android:
public void onClick(View v) {
try {
InetAddress serverAddr = InetAddress.getByName("localhost");
Socket mySocket = new Socket(serverAddr, 666);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
C#:
TcpListener listener = new TcpListener(System.Net.IPAddress.Parse("127.0.0.1"), 666);
listener.Start();
using (Socket socket = listener.AcceptSocket())
{
using (Stream stream = new NetworkStream(socket))
{
}
}
When hitting the line Socket mySocket = new Socket(serverAddr, 666); in my Android application I am getting the following error.
"java.net.ConnectException:
localhost/127.0.0.1:666 - Connection
refused"
Anyone able to guide me as to what I am doing wrong?
PS: I am testing this through the emulator so wondering if there is possibly some sort of limitation about my ability to communicate with other processes running on the machine?

Inside the emulated machine the address 127.0.0.1 is not the host's loopback interface, it's the emulated machine's own loopback interface.
According to the emulator documentation you can access the host's loopback interface through the special address 10.0.2.2.

The exception details that you tried to connect to 127.0.0.1 from Android, this means your Android device. Since the server socket is on your Windows machine it cannot connect.

Related

Multiple UDP connections to different remote IPs with the same port

I have a need to talk to multiple devices on a private LAN using a proprietary UDP protocol. In a production setting we have a industrial PC running a C++ application that can connect to multiple devices and communicate freely with them. I am trying to duplicate that communication using C# for a windows application that technicians, testers and others would be using. I have probably done this myself a thousands times in c++ but c# seems to be giving me all sorts of fits.
I have one UDP listener listening on Any IP and specific Port. This port is different from the device command port. This receives a periodic heartbeat from each device. From this communication I am able to get the specific IP and command Port for that device. The program maintains a list of devices and displays that lists to the user. The user can then select a specific device and inspect it more for more details.
If there are several devices with the same port number the program will not be able to inspect those devices at the same time. When the user selects the device the program creates a new instance of the UdpClient. In pseudo-code form:
udpConnection = new UdpClient();
udpConnection.ExclusiveAddressUse = false;
udpConnection.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpConnection.Client.Bind(localEndpoint);
udpConnection.Client.Connect(remoteEndpoint);
Local Endpoint is the Local interface IP and the Device Port Number of the machine the application is running on. Remote EndPoint is the Device IP and Device Port that the application wants to inspect further.
As anyone had similar issues and what have you done to get around it?
Thanks in advance
Update sample network diagram and further explanation:
Network Diagram
In the image I will be able to have two windows viewing Device A and C or B and C simultaneously with no issues. However if I have Device A and C the window that I opened second will not get any communications updates until I close the first window. If I "sniff" the network with WireShark I see all the communications as I would expect.
Code Snippet:
private void ClientThread()
{
IPEndPoint myEndPoint;
myLogger = LogManager.GetLogger("ClientLogs");
myLogger.Debug("Client Started!");
IPAddress ClientAddress = System.Net.IPAddress.Parse(ClientIP);
myIP = "10.0.0.4"; // Currently hard-coded local interface IP
IPAddress thisAddress = System.Net.IPAddress.Parse(myIP);
ClientEndPoint = new IPEndPoint(ClientAddress, Convert.ToInt32(ClientPort));
myEndPoint = new IPEndPoint(thisAddress, Convert.ToInt32(ClientPort)); // Both forms launch but only the first one will receive data.
//myEndPoint = new IPEndPoint(thisAddress, 0); // Both forms will launch but no data received (packets do show being received in wireshark)
//myEndPoint = new IPEndPoint(IPAddress.Any, ClientPort); // Both forms launch but only the first one will receive data.
try
{
myUDP = new UdpClient();
myUDP.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); // "Only one usage of each socket address (protocol/network address/port) is normally permitted" Exception when removed.
myUDP.ExclusiveAddressUse = false; // No difference if this is removed
myUDP.Client.Bind(myEndPoint); // Neither form will receive data if this is removed
myUDP.Client.Connect(ClientEndPoint); // removing this will allow the forms to launch but again the only the first will receive data
}
catch (Exception ex)
{
myUDP = null;
myLogger.Fatal(String.Format("Error in setting up UDP Client: {0}", ex.Message));
return;
}
myLogger.Debug(String.Format("Attempt to connect to : {0} on {1}", ClientIP, Convert.ToInt32(ClientPort)));
byte[] bytes = new byte[1452];
try
{
while (ThreadLoop)
{
IPEndPoint newEndPoint = new IPEndPoint(IPAddress.Any, 0);
Byte[] receiveBytes = myUDP.Receive(ref newEndPoint);
ParseProtocolPacket(ref receiveBytes); // Code to parse the data received
}
}
catch (Exception Ex)
{
myLogger.Debug("Client Socket Other Error: " + Ex.Message);
}
}
I think your problem is here:
udpConnection.Client.Bind(localEndpoint);
This line, if I understand correctly, is telling it to use the same local port to make the outbound request. But you already have another UdpClient listening on that port, so Windows won't know which one to send the traffic to (or it just sends it to the first one).
You should be able to just not use Bind() here. Without it, when you call Connect(), it will assign a random local port, which is the way most outbound network requests work.
Or if you need to specify the network interface, then pass 0 for the port and Windows will assign one:
localEndpoint = new IPEndPoint(ipAddress, 0);

WIFI Direct IP Address issue

I have checked and found that the problem is the ip address being assigned to the connectionEndpointPair is carrying the IP of the wi-fi direct network adapter and i don't know how to open the port on that specific ip, the ip is different from when i ping it from my pc the windows is listening on port 5009 and connection established when i use the wi-fi ip but when i use the wi-fi direct ip addresses i'm having an issue
The wi-fi direct connection between the device and the windows 8.1 application is ok, I then am awaiting for my sockets to connect but it does not happen what could be the issue ?
I get error on Visual Studio:
No connection could be made because the target machine actively refused it. (Exception from HRESULT: 0x8007274D)
On the Windows side i am using this code:
String deviceSelector = WiFiDirectDevice.GetDeviceSelector();
DeviceInformationCollection deviceCollection = await DeviceInformation.FindAllAsync(deviceSelector);
if(deviceCollection.Count > 0)
{
try
{
wfdDevice = await WiFiDirectDevice.FromIdAsync(deviceCollection[0].Id);
wfdDevice.ConnectionStatusChanged +=ConnectionStatusChangedNotficationHandler;
var endpointPairs = wfdDevice.GetConnectionEndpointPairs();
EndpointPair connectionEndpointPair = endpointPairs[0];
try
{
connectionEndpointPair.RemoteServiceName = "5009";
StreamSocket socket = new StreamSocket();
await socket.ConnectAsync(connectionEndpointPair);
string s = "hello";
}catch (Exception err)
{
string s = err.Message;
s = err.StackTrace;
}
}
catch (Exception err)
{
string error = err.Message;
}
On the android side i am using this code:
private void initiateClientSocket(String hostAddress) {
int timeout = 10000;
int port = 5009;
InetSocketAddress socketAddress
= new InetSocketAddress(hostAddress, port);
try {
Socket socket = new Socket();
socket.bind(null);
socket.connect(socketAddress, timeout);
} catch (IOException e) {
Log.e(TAG, "IO Exception.", e);
}
// TODO Start Receiving Messages
}
From the android side I am getting:
java.net.UnknownHostException: Host is unresolved: my ip
Can any please help
Thanks :)
Even if you have a direct WIFI Connection between the Android phone and the windows computer, you need a server and a client for a tcp connection.
I don't know the purpose of your application but I assume that the windows computer is the better choice for the server. So instead connecting to the socket, on the computer you should open a listener for the port.
The server class that is related to the chosen StreamSocket class is the StreamSocketListener. You can find the Documentation here: http://msdn.microsoft.com/en-us/library/windows/apps/windows.networking.sockets.streamsocketlistener.aspx
There is also a paragraph in this documentation about the typical order of operations:
Create the StreamSocketListener.
Use the Control property to retrieve a StreamSocketListenerControl object and set the socket quality of service required.
Assign the ConnectionReceived event to an event handler.
Call the BindServiceNameAsync or BindEndpointAsync method to bind to a local TCP port or service name.
When a connection is received, use the StreamSocketListenerConnectionReceivedEventArgs object to retrieve the Socket property with the StreamSocket object created.
Use the StreamSocket object to send and receive data.
Call the Close method to stop listening for and accepting incoming network connections and release all unmanaged resources associated with the StreamSocketListener object. Any StreamSocket objects created when a connection is received are unaffected and can continue to be used as needed.
I haven't worked with this special class, but the basics of TCP are always the same...
I don't quite understand your code on Window, but guess that there is something wrong with the following code
connectionEndpointPair.RemoteServiceName = "5009";
It seems that "RemoteServiceName" has nothing to do with the port number 5009. Please check other fields in the struct/object "connectionEndpointPair" and make proper settings.

Error while making connection using TCP Client

I am trying to make connection with remote system in the network using C#. then the program is throwing the following exception
No connection could be made because the target machine actively refused it 192.168.1.42:8000
private void Start_Sending_Video_Conference(string remote_IP,int port_number)
{
try
{
ms = new MemoryStream();// Store it in Binary Array as
pictureBox1.Image.Save(ms,System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] arrImage = ms.GetBuffer();
myclient = new TcpClient (remote_IP,port_number);//Connecting with server
myns = myclient.GetStream ();
mysw = new BinaryWriter (myns);
mysw.Write(arrImage);//send the stream to above address
ms.Flush();
mysw.Flush();
myns.Flush();
ms.Close();
mysw.Close ();
myns.Close ();
myclient.Close ();
}
catch (Exception ex)
{
Capturing.Enabled = false;
MessageBox.Show(ex.Message, "Video Conference Error Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Please check the usual suspects:
Is server application really running
Does it really listen on port 8000?
Does firewall on client computer allow outgoing traffic on port 8000?
Does firewall on server computer allow incoming traffic on port 8000?
Are you sure something is listening on the other end? In this case, it appears that your local server is actually denying the request. Please confirm that the server is running, the TCPServer is listening, and that the machine the server is running from (if it's locally, this shouldn't be a problem) is setup to allow incoming packets from the LAN.
If the solutions above didn't work, then the problem is probably in the Server code.
you may have used an instance of TcpListener to listen to the specified port, but which IpAddress did you pass to the constructor?
If you wrote the following code:
mylistener = new TcpListener(IPAddress.Loopback, 8000);
It will result in that error.
This happens because The Loopback dosen't make the listener listen to all the network interfaces, but only the requests coming from the localhost (127.0.0.1).
Use this code instead
mylistener = new TcpListener(IPAddress.Any, 8000);

Sending and receiving UDP packets in .NET

I am trying to test UDP communications on a LAN. I have a small piece of code to and I have tried to run it in 2 computers (one should wait to receive and the other one should send). The strange thing is that computer A sends and B receives properly but if I try A to receive and B to send it does not work. Do you know why could it be?
public void SendBroadcast(int port, string message)
{
UdpClient client = new UdpClient();
byte[] packet = Encoding.ASCII.GetBytes(message);
try
{
client.Send(packet, packet.Length, IPAddress.Broadcast.ToString(), port);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
public void Receive(int port)
{
UdpClient client = null;
try
{
client = new UdpClient(port);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
IPEndPoint server = new IPEndPoint(IPAddress.Any, 0);
while (true)
{
try
{
byte[] packet = client.Receive(ref server);
Console.WriteLine("{0}, {1}", server, Encoding.ASCII.GetString(packet));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
And the calls:
SendBroadcast(444, "hello"); Receive(444);
If I run 2 instances of the program on the same computer it works properly but creates 3 packages per call.
Thanks in advance.
Try using the async methods so that you can keep listening for messages without blocking to send messages.
Well, if the same code works on one and not the other, it's your environment. Check your firewall settings, make sure it's not preventing the broadcast on the sender or preventing receipt on the receiver. Wireshark (or even Windows' netmon) should be helpful here.
What networking gear is inbetween these two systems?
Are the two systems on the same subnet with the same subnetmask?
There's a funny thing with IPV4 networks; you can have multiple broadcast addresses. You can broadcast to the local network or to the local subnet. These are distinctly different addresses, and if one system's IP setup is different it may not realize that it should listen for this local subnet broadcast.
Things to try:
Ensure IPV6 is disabled on both ends (IPV6 doesn't support broadcast address, but lets just establish a baseline).
Explictly set the IP address in the program, does it work? My guess will be yes, so we have to determine why.
Load up wireshark and sniff the packets. See if they are making it all the way to the remote host, and he is just ignoring them.
When trying to do this asynchronously, Microsoft neglects to tell users to create their own partial class like this (see below). Very simple, but without this, it can be difficult to read through their examples.
private partial class UdpState
{
public UdpClient u;
public IPEndPoint e;
}

Test for possible remote connection

Supposing i know the ip of a pc, is it possible to test if that pc supports remote connection?
(windows case)
i figured it out like this
private bool TestPort(string ipString,int port)
{
IPAddress ip = IPAddress.Parse(ipString);
bool test = false;
try
{
System.Net.Sockets.Socket s = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
s.Connect(ip, port);
if (s.Connected == true)
test = true;
s.Close();
}
catch (SocketException ex)
{
test = false;
}
return test;
}
if the function were in c++ would it be faster? how much faster? any suggestions?
This appears to work:
http://www.yougetsignal.com/tools/open-ports/
Type in the IP address and then use port "3389" to check for native windows remote desktop.
One way to test if Remote Desktop is available, could be to open a socket to the default RD port (3389). If a connection can be established, assume that RD is available and drop the socket. If connection is refused, RD is most likely not available.
Another approach would be to access information about RD via WMI. This would require the client computer to have sufficient user rights on the (possible) server, though. Inspiration for this approach can be found here:
http://www.vedivi.com/support/blog/71-how-to-enable-remote-desktop-programmatically.html

Categories