How to transfer Data between Android devices using wifi direct? - wifi-direct

I need to pass String values to the devices connected through Wifi-Direct..how can i pass string between two connected device..I am using Wifi-Direct file transfer example available as reference.
In doInBackground method of FileServerAsyncTask I am using the code
ServerSocket serverSocket = new ServerSocket(8988);
Socket client = serverSocket.accept();
PrintWriter out = new PrintWriter(client.getOutputStream(),true);
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
How do i modify onHandleIntent method? Any reference to this kind of implementation will be helpful. Thanks

There are some things that you should consider while sending data via wifi direct
Once connected, one device will be group owner and the other will be client
The group owner will have fixed IP address i.e. 192.168.49.1
You will know which became group owner only at runtime.
Once connected, you have to send some data from client to server that contains information about its IP address. This is done because server will have no idea of client's IP address.
That way, you can only send data. Because, by this time you will know which device has what IP address.
Cheers.

Related

UDP Listen, Send Receive (Simple, Client and Server on same app)

Okay, I want to send a UDP packet to an IP, and then receive it.
As I can't get it to work, I have to ask for assistance.
I want it to work on 1 app, meaning client and server is on the same application.
I currently got it working with Audio sending and receiving on the same app (using sample codes and stuff).
And the thing I can´t understand is just the UDP, and probably Sockets.
It seems simple, but I can´t get it to work.
So if I can get a very simple sample, like:
"UDP Send "hello" to IPofchoice"
"UDP receive "data" from IPofchoice"
Messagebox.show("decoded(data));
Well hope you get what I mean.
EDIT:
Here is my "example" which doesn´t work at all.
void VoiceChat_KeyPress(object sender, KeyPressEventArgs e)
void VoiceChat_KeyPress(object sender, KeyPressEventArgs e)
{
string text = "Hello";
byte[] send_buffer = Encoding.ASCII.GetBytes(text);
otherPartyIP = new IPEndPoint(IPAddress.Parse(txtCallToIP.Text), 1450);
udpClientKey.Send(send_buffer, send_buffer.Length, "127.0.0.1", 1450);
byte[] byteData = udpClientKey.Receive(ref otherPartyIP);
MessageBox.Show(otherPartyIP.Address.ToString());
MessageBox.Show(System.Text.Encoding.ASCII.GetString(byteData));
}
Where txtCallToIP.tex = the ip i write, which is 127.0.0.1 currently.
This i solved.
To have a client and server in UDP it´s very easy, though a bit dangerous, as you don´t know for sure if it´s working or not unless you test it (UDP just send and don´t care about anything else).
So basically to do it.
Client.Send(buffer,0,buffer.size,IPAdress,Port);
byte[] rec = Client.Receive(ref IPAdress);
To receive you must have bind it to an IP, so you can just bind it to listen to Any ipadress,
The port however needs to be set (i think), and you want to do that, as listening to everything there is, is not a good idea.
So ref IPAdress will be that listening IP and Port.
So it´s very easy to set up. And you can use the same UDPClient for both receiving and sending if you want, though it´s probably better to have 2 separate .

Azure client IP address

I haven't been able to find any documentation on how to predict the IP address that Azure sees you as.
Here's the IP that I'm referring to, in red:
I'm trying to implement CURRENT CLIENT IP ADDRESS xxx.xxx.xxx.xxx ADD TO ALLOWED IP ADDRESSES programmatically.
Here is what worked for me: There is a "AutoDetectClientIP" Management API call that updates an existing Firewall Exception to the caller's IP address.
But you need access to a Management Certificate that is valid for the given subscription, the subscription ID, the name of the SQL Azure Server and the name of the Firewall Exception.
public static bool SetFirewallRuleAutoDetect(string certFilename, string certPassword, string subscriptionId, string serverName, string ruleName)
{
try
{
string url = string.Format("https://management.database.windows.net:8443/{0}/servers/{1}/firewallrules/{2}?op=AutoDetectClientIP",
subscriptionId,
serverName,
ruleName);
HttpWebRequest webRequest = HttpWebRequest.Create(url) as HttpWebRequest;
webRequest.ClientCertificates.Add(new X509Certificate2(certFilename, certPassword));
webRequest.Method = "POST";
webRequest.Headers["x-ms-version"] = "1.0";
webRequest.ContentLength = 0;
// call the management api
// there is no information contained in the response, it only needs to work
using (WebResponse response = webRequest.GetResponse())
using (Stream stream = webResponse.GetResponseStream())
using (StreamReader sr = new StreamReader(stream))
{
Console.WriteLine(sr.ReadToEnd());
}
// the firewall was successfully updated
return true;
}
catch
{
// there was an error and the firewall possibly not updated
return false;
}
}
Your IP address is determined by the NATting of the network that you are on, unless you are coming from a machine that has a fixed public IP address. Unless you have client machines connecting from the same network, and you understand the network in detail, it is unlikely that you can reliably predict the client IP addresses. The only solution is to add a range from say 86.0.0.0 to 86.255.255.255 and hope that it covers the network that you are connecting from - but a whole lot of 'undesirables' will land up in that range too.
The client IP address functionality should not be used for anything other than direct admin access, which can be manually set from time to time as needed. It can also be locked down using local firewall rules too, by restricting access over port 1433 to specific local network machines. Any more general access should be restricted to a service of sorts - such as OData style, mobile services, or using some sort of port bridge, which can be facilitated by VPNs, VMs and other IaaS services.
I suggest you think strongly about your use case first - direct SQL access is not a viable pattern for cloud computing. Many alternatives exist that are faster, more secure, and more manageable. Besides, at the very least you are entering a world of pain trying to get the guys in security to poke holes in their firewalls for SQL ports.

Get TCP address information in ZeroMQ

I want to connect clients to a server using ZeroMQ (java bindings, jzmq), but I need the TCP information badly, for example the TCP/IP address of a client request! The problem is, for being able to announce a service in the network I need to grab the TCP address of a request to be able to redirect clients to that service. The broker is a central "service registry" in that case. However, having ZeroMQ services on both sides, I do not see an option to retrieve that information.
What I do now, is to establish a dummy connection using a standard socket to the broker, after the connection is established I grab the IP address used for this connection and close the connection again. The IP address which has been retrieved is now being used for binding on it using a ZeroMQ socket on a random port.
I think this solution is the ugliest solution ever possible, so: What is a better solution to this problem?
Greetings.
0MQ doesn't provide the address of peers, for a number of reasons. It's also not that useful since what you really want is the endpoint to receive connections on, not the address the connection was made on.
What I usually do, and it's elegant enough, is pass bind a service to an ephemeral port, get a full connection endpoint ("tcp://ipaddress:port") and send that string in some way, either broadcast to peers, to a central registry, etc. along with my service name. Then, peers who want to connect back can take the service name, look up to find my endpoint, and connect back to me.
In ZMQ 4.x, you may get the string property "Peer-Address" or the "Identity" property. http://api.zeromq.org/4-2:zmq-msg-gets
The Identity is set in the other peer before connect(). http://api.zeromq.org/4-2:zmq-setsockopt#toc20
For example,
const char *identityString = "identity";
zmq::context_t context(1);
zmq::socket_t socket(context, ZMQ_REQ);
socket.setsockopt(ZMQ_IDENTITY, identityString, strlen(identityString));
socket.connect("tcp://127.0.0.1:5555");
Then the other side:
while(1)
{
zmq::message_t request;
if (socket.recv(&request, ZMQ_NOBLOCK))
{
const char* identity = request.gets("Identity");
const char* peerAddress = request.gets("Peer-Address");
printf("Received from %s %s\n", peerAddress, identity);
break;
}
}
I'm using CppZmq btw, you should be able to find the relevant calls easily.
Digging deeper into the libzmq code, I discovered that the library attaches to every message instance the file descriptor that it was received on.
This worked for me
int sockfd = zmq_msg_get(&msg, ZMQ_SRCFD);
sockaddr_in addr;
socklen_t asize = sizeof(addr);
getpeername(sockfd, (sockaddr*)&addr, &asize);
std::cout << inet_ntoa(addr.sin_addr) << ":" << addr.sin_port << std::endl;
Note that the FDs can and will be reused by other connections.
I'm working with version 4.2.1 of the api using the CZMQ binding and I found a solution for my case (ZMQ_STREAM). It works by setting an id before connecting.
The relevant socket option is "ZMQ_CONNECT_RID".
ZMQ api via zmq_setsockopt()
CZMQ api via zsock_set_connect_rid()
Some codes with redacted redacted ips.
const char endpoint1[] = "tcp://1.2.3.4:12345"
const char endpoint2[] = "tcp://5.6.7.8:12345"
zsock_t *stream = zsock_new(ZMQ_STREAM);
zsock_set_connect_rid(stream, endpoint1);
zsock_connect(stream, endpoint1);
zsock_set_connect_rid(stream, endpoint2);
zsock_connect(stream, endpoint2);
Then I get those 2 messages if there is a connection. First frame is the id and second frame is empty on connect/disconnect for ZMQ_STREAM sockets.
[Message1]
[019] tcp://1.2.3.4:12345
[000]
[Message2]
[019] tcp://5.6.7.8:12345
[000]
Another option is to use the zmq_socket_monitor() or czmq zmonitor. It was one of my first solution but I was looking for something lighter. I was able the get the endpoint that way without setting the id directly on the socket.
The zmonitor zactor make it possible to subscribe to socket events and then it sends a message with 3 frames:
[009] CONNECTED
[002] 14
[021] tcp://127.0.0.1:33445

How does a socket know which network interface controller to use?

If a computer has multiple network cards, all of them connected to different networks and functioning properly, when we open a socket, how does the OS determine which NIC to use with this socket? Does the socket API allow us to explicitly specify the NIC that is to be used?
I'm writing this from a Linux perspective, but I suppose it applies everywhere.
The decision is made when the socket is bound. When bind is called, the address you specify determines the interface the socket will listen on. (Or even all interfaces.)
Even if you don't use bind, it happens implicitly when you connect. The destination is looked up in the route table, which must contain a route to the destination network. The route also contains the interface to use and can optionally even specify the source address. If no source address is specified, the primary address of the interface is taken.
You can actually use bind together with connect, to force your outgoing connection to use a specific address and port. A socket must always have these two bits of information, so even when you don't, the primary address is used and a random port are chosen.
I dont know why im included in the edit suggestion when i was not even related to this question .I got similar edit suggestion before as well..might be some bug/issue.
(If you feel inclined to up-vote, #Shtééf's answer deserves it more than mine.)
That depends on whether you are connecting or binding.
If you bind, you can bind to a specific IP address corresponding to one of the machine's interfaces, or you can bind to 0.0.0.0, in which case the socket will listen on all interfaces.
If you connect an unbound socket, then the machine's routing tables, in conjunction with the destination IP adress, will determine which interface the connection request goes out on.
It is possible to bind a socket then connect it. In this case, the socket will remain bound as per the bind call when it makes the connection. (Thanks to #RemyLebeau for pointing this out.)
I'm not really sure which method is the best, but there is an alternative theory to the bind()-before-connect() approach that Shtééf presented. It's to use setsockopt() with SO_BINDTODEVICE . See: http://codingrelic.geekhold.com/2009/10/code-snippet-sobindtodevice.html
As an alternative, you can search for the appropriate nic based on its name:
//Find the ip address based on the ethernet adapter name. On my machine the ethernet adapter is "Ethernet"
System.Net.NetworkInformation.NetworkInterface[] nics = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
System.Net.NetworkInformation.NetworkInterface ethernet = nics.Where(n => n.Name.Equals("Ethernet")).Single();
UnicastIPAddressInformation uniCastIPAddressInformation = ethernet.GetIPProperties().UnicastAddresses.Where(a => a.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork).Single();
IPEndPoint localEndPoint = new IPEndPoint(uniCastIPAddressInformation.Address, 9000);
//Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//Bind and start listening
listener.Bind(localEndPoint);
listener.Listen(10);

BroadCasting

Ok in order to broadcast, I have created a socket:
notifySock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
And to send the hostname of my computer to all other computers connected to the same lan, I am using the send(Byte[] buffer) method:
notifySock.Send(hostBuffer);
hostBuffer contains the hostname of my computer.
However because I am using a 'datagram' socket-type do I need to format the data I need to send.
If possible please provide the code that I must put in between the two lines of code I have entered to create a socket and send the data.
For broadcast from a user application, UDP is typically used. You need to design a suitable protocol, i.e. a way to format the information you want to send into the UDP packet.
In your example you haven't specified who you are sending to. You need something like:
UdpClient notifySock = new UdpClient(endPoint);
notifySock.Send(buffer, buffer.Length, new IPEndPoint(IPAddress.Broadcast, 1234));
For the other hosts on your LAN to receive that they have to be listening on UDP port 1234.