TCP hole punching, can't reuse address on android - android

I have an android device hosting an HTTP server and is NATed(behind router). I want to access it from a public server which is not NATed.
I run a HTTP server on android device at port 8080 in a thread and after some time, I launch a client thread which tries to connect to remote public server from local port number 8080 on android.
For some reason, android client won't connect after I start server on port 8080. Nor does it yield any exception. Here is my code:
Thread server = new Thread(new Runnable() {
public void run() {
super.run();
try {
ServerSocket serverSocket = new ServerSocket();
serverSocket.setReuseAddress(true);
serverSocket.bind(new InetSocketAddress("192.168.1.102", 8080));
while(isRunning){
try {
System.out.println("Listening for new connection");
Socket socket = serverSocket.accept();
System.out.println("incoming connection accepted");
new Thread(new ConnectionHandler(socket)).start();
} catch (IOException e) {
e.printStackTrace();
}
}
serverSocket.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
});
server.start();
// sleep several seconds before launch of client
Thread.currentThread().sleep(5 * 1000);
Thread client = new Thread(new Runnable() {
public void run() {
super.run();
try {
/* .. */
Inet4Address localaddr = (Inet4Address) InetAddress
.getByName("192.168.1.102");
// Inet4Address remoteaddr = (Inet4Address)
// InetAddress.getByName("122.176.73.10");
System.out.println("connecting to 122.176.73.10");
Socket socket = new Socket();
socket.setReuseAddress(true);
System.out.println("[Client]socket.isBound():" + socket.isBound());
socket.bind(new InetSocketAddress("192.168.1.102", 8080));
for (int i = 1; i < 5; i++) {
try {
socket.connect(new InetSocketAddress("122.176.73.10", 4040));
System.out.println("connected to 122.176.73.10");
break;
} catch (Exception e) {
System.out.println("[Client]fail to connect ");
Thread.currentThread().sleep(i * 2 * 1000);
}
}
}
}
});
client.start();

A port number can't be used to both listen for incoming connections and make an outgoing connection. Your listening socket on 8080 prevents anything else using that port.

Related

In ANDROID how to pass values to a background thread which has an open socket connection

I am trying to pass keyboard values to an android client to push it to a server.
I am using threads, but don't want to run a new thread or call socketconnect each time. Instead, I want to run a single thread, open socket connection and then use the same thread and already opened socket to push some values to server from keyboard.
A runnable example with handler will work in my case but I don't know how to code it. ASYNCTASKS wont help as it would open connection again and again.
My Connection class is
class conThread implements Runnable {
public Handler dataHandler = new Handler() ;
#Override
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVERPORT);//}
} catch (IOException e) {
e.printStackTrace();
}
}
}
**and my button has got the below code to send values to the thread for passing on to the server **
public void dataSend(View view) {
conThread con = new conThread();
new Thread(con).start();
con.dataHandler.post(new Runnable() {
public void run() {
try {
PrintWriter out = new PrintWriter(socket.getOutputStream());
Log.d("Client", "S: data");
out.print("3333");
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
I get connected to the server but get a crash after that.

Serversocket.accept() not accepting connection in server side when implemented in a background service

I am trying to establish a client server socket connection with wifi direct using the demo WiFi direct app. The demo app works fine where the connection is being established when the activity is open but
if I create a background service and try to listen for socket connections, the server running in the background service does not accept connections.
The code is as given below:
Server:
public class MyBackgroundService extends Service implements ChannelListener, ConnectionInfoListener {
private Runnable runnable = new Runnable() {
#Override
public void run() {
// put your socket-code here
String filename= null;
// Toast t = Toast.makeText(context,"Opening a server socket",Toast.LENGTH_LONG);
// t.show();
DataInputStream inputstream = null;
try {
ServerSocket serverSocket = new ServerSocket(8988);
Log.e(WiFiDirectActivity.TAG, "Server: Socket opened");
Socket client = serverSocket.accept();
Log.e(WiFiDirectActivity.TAG, "Server: connection done");
....
}
#Override
public void onConnectionInfoAvailable(final WifiP2pInfo info) {
this.info = info;
if (info.groupFormed && info.isGroupOwner) {
Log.e(WiFiDirectActivity.TAG,"FileServeronConneitoninfo Background");
new Thread(runnable).start();
}
}
Client:
public class FileTransferService extends IntentService {
private static final int SOCKET_TIMEOUT = 0;
#Override
protected void onHandleIntent(Intent intent) {
Context context = getApplicationContext();
if (intent.getAction().equals(ACTION_SEND_FILE)) {
String filename= intent.getExtras().getString(EXTRAS_FILE_PATH);
String host = intent.getExtras().getString(EXTRAS_GROUP_OWNER_ADDRESS);
Socket socket = new Socket();
int port = intent.getExtras().getInt(EXTRAS_GROUP_OWNER_PORT);
DataOutputStream stream = null;
try {
Log.e(WiFiDirectActivity.TAG, "Opening client socket - ");
socket.bind(null);
Log.e(WiFiDirectActivity.TAG, "Opening client socket - ");
socket.connect((new InetSocketAddress(host, port)), SOCKET_TIMEOUT);
Log.e(WiFiDirectActivity.TAG, "Client socket - " + socket.isConnected());
// ...
}
catch (IOException e) {
Log.e(WiFiDirectActivity.TAG, "IOException in File transfer");
Log.e(WiFiDirectActivity.TAG, e.getMessage());
}
finally {
if (socket != null) {
if (socket.isConnected()) {
try {
socket.close();
stream.close();
} catch (IOException e) {
// Give up
e.printStackTrace();
}
}
}
}
The client side is getting timeout exception and both the lines after the connect and accept are not executing. Is there any possible reason?
I have put timeout 0 to prevent timeout exception but still there are no connections established. This is happening only in the background service but if I do this in activity everything works fine.
Thanks in advance.
Log Cat Output of server side:
01-28 11:21:12.391 E/wifidirectdemo: COnnection_Change_BackgroundService
01-28 11:21:12.392 E/wifidirectdemo: ConnectionInfo Available Background
01-28 11:21:12.392 E/wifidirectdemo: FileServeronConneitoninfo Background
01-28 11:21:12.394 E/wifidirectdemo: Server: Socket opened
01-28 11:21:22.877 E/wifidirectdemo: P2P peers changed

Android Socket Connectio Refused

I am having trouble connecting two android phones via socket i am using android debug bridge to connect the phones to my PC from which i can launch the emulator on the phones.
I launch the server on one phone and try to connect with the other however i get the following error on my client side:
W/System.err: java.net.ConnectException: failed to connect to /192.168.49.1 (port 8080): connect failed: ECONNREFUSED
Server
private class SocketServerThread extends Thread {
static final int SocketServerPORT = 8080;
#Override
public void run() {
try {
serverSocket = new ServerSocket(SocketServerPORT);
Log.d("Quiz", "Server creation connection success");
Log.d("Quiz", "Server local port "+serverSocket.getLocalPort());
Log.d("Quiz", "Server local port "+serverSocket.getInetAddress());
HostingScreen.this.runOnUiThread(new Runnable() {
#Override
public void run() {
}
});
while (true) {
Socket socket = serverSocket.accept();
count++;
message += "#" + count + " from " + socket.getInetAddress()
+ ":" + socket.getPort() + "\n";
HostingScreen.this.runOnUiThread(new Runnable() {
#Override
public void run() {
msg.setText(message);
}
});
SocketServerReplyThread socketServerReplyThread = new SocketServerReplyThread(
socket, count);
socketServerReplyThread.run();
}
} catch (IOException e) {
e.printStackTrace();
}
}
Client
#Override
protected Object doInBackground(Object[] params) {
Socket socket = null;
try {
socket = new Socket(host,port);
Log.d("Quiz", "Client socket success");
connected = true;
while (connected) {
try {
Log.d("Quiz", "Sending command");
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket
.getOutputStream())), true);
// where you issue the commands
} catch (Exception e) {
}
}
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(socket != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
The port is hard coded to port 8080 for both the server and the client for the time being, the host address is found when i make a connection between the phones by using the following code:
Connection
private void onConnectionChanged(Intent intent) {
final NetworkInfo netInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
final WifiP2pInfo p2pInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO);
isConnected = netInfo.isConnected();
if (isConnected) {
//Get host connection info
wifiMgr.requestConnectionInfo(channel, new ConnectionInfoListener() {
#Override
public void onConnectionInfoAvailable(final WifiP2pInfo info) {
wifiMgr.requestGroupInfo(channel, new GroupInfoListener() {
#Override
public void onGroupInfoAvailable(WifiP2pGroup group) {
if (group == null)
return;
WiFiP2P.this.group = group;
Log.d(TAG, "Wifi p2p connection group is " + group.getNetworkName());
Log.d(TAG, "Group size " + group.getClientList().size());
fireOnConnectionSucceed(group.getNetworkName(), group.getPassphrase());
//create client if not host
if(info.isGroupOwner) {
Client client = new Client(8080, p2pInfo.groupOwnerAddress.getHostAddress());
client.execute();
Log.d(TAG, "Client launch success");
Log.d(TAG, "Host address " + p2pInfo.groupOwnerAddress.getHostAddress());
}
}
});
if (isConnected && !info.isGroupOwner) {
} else {
startDiscovery();
}
}
});
} else {
group = null;
fireOnConnectionLost();
}
}
I check to see if the person connected is the host or not, if not i launch the client passing the port and host address to the client which is an Aysnc task where the socket to connect is created.
The error occurs in the client when
socket = new Socket(host,port);
is used causing the error stated.
Any ideas as to what the problem could be? They both connect to each other over WiFi but when i try to connect to the server socket it fails.
Thanks in advance.
Edit:
To clear somethings up, i use the adb to get the app from my computer onto my phone from which i can launch the app.
I am connecting both phones using wifimanager i need to find which of the phones created the wifi group and then that person is the host of the server to which i can connect the problem arises when i try to launch a socket to connect to the host using the host address from the connect info.
I managed to solve my problem, it turns out the device which was hosting the server wasn't being designated the group owner.
config.groupOwnerIntent=0;
Setting the owner intent of connecting devices to 0 fixed the problem.

Getting socket timeout when receiving frequent requests at once

I attempting to build a remote controller for my laptop using my phone.
I written a server application that running on my laptop, the remote app used as a client to the server application.
I want to implement a mouse pad, the problem is when I am moving my finger over the "touch pad" too fast, I am receiving read time out on server side after few iterations.
Server code
final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(20);
Runnable serverTask = new Runnable()
{
#Override
public void run()
{
ServerSocket serverSocket = null;
try
{
serverSocket = new ServerSocket(DEFAULT_PORT);
serverSocket.setReuseAddress(true);
_working = true;
while (_working)
{
Socket clientSocket = serverSocket.accept();
clientSocket.setSoTimeout(10000);
clientProcessingPool.submit(new ClientTask(clientSocket));
}
}
catch (IOException e)
{
System.err.println("Unable to process client request");
e.printStackTrace();
}
finally
{
try
{
if (serverSocket != null)
{
serverSocket.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
};
Thread serverThread = new Thread(serverTask);
serverThread.start();
private class ClientTask implements Runnable
{
private final Socket clientSocket;
private ClientTask(Socket clientSocket)
{
this.clientSocket = clientSocket;
}
#Override
public void run()
{
System.out.println("Got a client !");
try
{
System.out.println("Connected!");
DataOutputStream dOut = new DataOutputStream(clientSocket.getOutputStream());
DataInputStream dIn = new DataInputStream(clientSocket.getInputStream());
String request = dIn.readUTF();
parseRequest(request);
System.out.println("request=" + request);
dOut.writeUTF("Got the command");
dOut.flush(); // Send off the data
dIn.close();
dOut.close();
clientSocket.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
I thought maybe I will send the requests only if the distance from the starting position to end position is bigger than STEPS(a constant) and only then send the request. But I think the mouse won`t move fluidly.
Thanks.
RXAndroid and RXJava are perfect for asynchronously handling these request and will allow you to add a debounce to the frequent requests. Check out Reactive.io

Android and Arduino socket

I have created a server and client with Android and Arduino but I have a problem. Android reads only one time. Why? this is my code:
Client Android:
new Thread(new ClientThread()).start();
}
class ClientThread implements Runnable {
#Override
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName("192.168.1.240");
socket = new Socket(serverAddr, 8888);
if(socket == null)System.out.println("SOCKET NULL");
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),true);
inFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while(true){
msgFromServer = inFromServer.readLine();
System.out.println(msgFromServer);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (socket != null) {
System.out.println("STOP SOCKET");
// close socket
}
}
}
}
Arduino Server:
void loop() {
YunClient client = server.accept();
sensorValue = analogRead(sensorPin);
String myString = String(sensorValue);
if (client) {
String command = "none";
command = client.readString();
Serial.println(sensorValue);
client.print(myString+"\n");
}
}
LOGCAT:
07-24 11:44:24.468: D/OpenGLRenderer(19693): Enabling debug mode 0
07-24 11:44:25.363: I/System.out(19693): 121
121 is the value from Arduino. But this is showing only once.
It works only once. I want receive data from the Arduino every second.
Thank you guys!
You need to take the accept out of the loop. otherwise it send a string and wait for another connect from client.
YunClient client = server.accept();
void loop() {
sensorValue = analogRead(sensorPin);
String myString = String(sensorValue);
if (client) {
String command = "none";
command = client.readString();
Serial.println(sensorValue);
client.print(myString+"\n");
}
}
Also, I don't see where the client sends something to the server. Instead of System.out.println should't it be out.println?

Categories

Resources