Transfer data from Client to Server using Sockets
In the previous post - Connect Two Android Devices over WiFi using Network Service Disocvery, we showed how we used Network Service Discovery
to connect two android devices over WiFi. In this post, we are going to show how we used this to our advantage to connect and send data to the server client.
We used the most basic thing that we found in the Android API - Socket
. Socket class provides a client-side TCP socket. Socket binds destination IP Address and a port to local IP Address and a local port. Read more here.
How to Create Connection between Client and Server
- Using NSD Manager, Client device should get server/host IP Address.
- Send data to server using Socket.
- Client should send its IP Address to server/host for bi-directional communication.
First step is done and we have obtained server’s IP Address. Now, we need to send Client devices’s IP Address to the server. For this we would use JSONObject
as JSONObject can be easily converted to String and sent via Socket.
Client Device
Obtain IP Address of Client’s Device
WifiManager wm = (WifiManager) getSystemService(WIFI_SERVICE);
String ipAddress = Formatter.formatIpAddress(
wm.getConnectionInfo().getIpAddress());
Connect to the Server and send IP Address using Socket
- Resolve the service and call a function to connect to the server.
- Create a JSONObject with fields
request
andipAddress
. - Create a new thread using
AsyncTask
for the Socket connection so that UI Thread doesn’t hang - In AsyncTask thread, create Socket connection. Send JSONObject as String and wait for Server’s repsonse.
public class ClientActivity extends Activity { | |
// NSD Manager, discovery listener code here | |
private int SocketServerPort = 6000; | |
private static final String REQUEST_CONNECT_CLIENT = "request-connect-client"; | |
NsdManager.ResolveListener mResolveListener = new NsdManager.ResolveListener() { | |
@Override | |
public void onServiceResolved(NsdServiceInfo serviceInfo) { | |
Log.d(TAG, "Resolve Succeeded. " + serviceInfo); | |
if (serviceInfo.getServiceName().equals(SERVICE_NAME)) { | |
Log.d(TAG, "Same IP."); | |
return; | |
} | |
// Obtain port and IP | |
hostPort = serviceInfo.getPort(); | |
hostAddress = serviceInfo.getHost(); | |
/* Once the client device resolves the service and obtains | |
* server's ip address, connect to the server and send data | |
*/ | |
connectToHost(); | |
} | |
}; | |
private void connectToHost() { | |
if (hostAddress == null) { | |
Log.e(TAG, "Host Address is null"); | |
return; | |
} | |
String ipAddress = getLocalIpAddress(); | |
JSONObject jsonData = new JSONObject(); | |
try { | |
jsonData.put("request", REQUEST_CONNECT_CLIENT); | |
jsonData.put("ipAddress", ipAddress); | |
} catch (JSONException e) { | |
e.printStackTrace(); | |
Log.e(TAG, "can't put request"); | |
return; | |
} | |
new SocketServerTask().execute(jsonData); | |
} | |
private String getLocalIpAddress() { | |
WifiManager wm = (WifiManager) getSystemService(WIFI_SERVICE); | |
String ip = Formatter.formatIpAddress(wm.getConnectionInfo().getIpAddress()); | |
return ip; | |
} | |
private class SocketServerTask extends AsyncTask<JSONObject, Void, Void> { | |
private JSONObject jsonData; | |
private boolean success; | |
@Override | |
protected Void doInBackground(JSONObject... params) { | |
Socket socket = null; | |
DataInputStream dataInputStream = null; | |
DataOutputStream dataOutputStream = null; | |
jsonData = params[0]; | |
try { | |
// Create a new Socket instance and connect to host | |
socket = new Socket(hostAddress, SocketServerPORT); | |
dataOutputStream = new DataOutputStream( | |
socket.getOutputStream()); | |
dataInputStream = new DataInputStream(socket.getInputStream()); | |
// transfer JSONObject as String to the server | |
dataOutputStream.writeUTF(jsonData.toString()); | |
Log.i(TAG, "waiting for response from host"); | |
// Thread will wait till server replies | |
String response = dataInputStream.readUTF(); | |
if (respnose != null && response.equals("Connection Accepted")) { | |
success = true; | |
} else { | |
success = false; | |
} | |
} catch (IOException e) { | |
e.printStackTrace(); | |
success = false; | |
} finally { | |
// close socket | |
if (socket != null) { | |
try { | |
Log.i(TAG, "closing the socket"); | |
socket.close(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
// close input stream | |
if (dataInputStream != null) { | |
try { | |
dataInputStream.close(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
// close output stream | |
if (dataOutputStream != null) { | |
try { | |
dataOutputStream.close(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
} | |
return null; | |
} | |
@Override | |
protected void onPostExecute(Void result) { | |
if (success) { | |
Toast.makeText(PlayListTestActivity.this, "Connection Done", Toast.LENGTH_SHORT).show(); | |
} else { | |
Toast.makeText(PlayListTestActivity.this, "Unable to connect", Toast.LENGTH_SHORT).show(); | |
} | |
} | |
} | |
} |
You may find this helpful
Connect devices using NSD
Use Network Service Discovery and Bonjour to connect devices over WiFi. This article will show you how to connect over WiFi and send files.
Server Device
After setting up the service using NSD Manager, wait for the client to connect and send request with IP Address. For this we used ServerSocket
. ServerSocket represents a server-side socket that waits for incoming client connections. A ServerSocket handles the requests and sends back an appropriate reply.
- Create a Thread in background.
- Initialize
ServerSocket
and wait for client to connect and send request. - Once client sends a request, perform some actions and give an appropriate response to the client.
public class ServerActivity extends Activity { | |
private int SocketServerPort = 6000; | |
private static final String REQUEST_CONNECT_CLIENT = "request-connect-client"; | |
private List<String> clientIPs; | |
// NSD Manager and service registration code | |
@Override | |
public void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
// NSD stuff. | |
clientIPs = new ArrayList<String>(); | |
socketServerThread = new SocketServerThread(); | |
socketServerThread.start(); | |
} | |
private class SocketServerThread extends Thread { | |
@Override | |
public void run() { | |
Socket socket = null; | |
DataInputStream dataInputStream = null; | |
DataOutputStream dataOutputStream = null; | |
try { | |
Log.i(TAG, "Creating server socket"); | |
serverSocket = new ServerSocket(SocketServerPORT); | |
while (true) { | |
socket = serverSocket.accept(); | |
dataInputStream = new DataInputStream( | |
socket.getInputStream()); | |
dataOutputStream = new DataOutputStream( | |
socket.getOutputStream()); | |
String messageFromClient, messageToClient, request; | |
//If no message sent from client, this code will block the program | |
messageFromClient = dataInputStream.readUTF(); | |
final JSONObject jsondata; | |
jsondata = new JSONObject(messageFromClient); | |
try { | |
request = jsondata.getString("request"); | |
if (request.equals(REQUEST_CONNECT_CLIENT)) { | |
String clientIPAddress = jsondata.getString("ipAddress"); | |
// Add client IP to a list | |
clientIPs.add(clientIPAddress); | |
messageToClient = "Connection Accepted"; | |
dataOutputStream.writeUTF(messageToClient); | |
} else { | |
// There might be other queries, but as of now nothing. | |
dataOutputStream.flush(); | |
} | |
} catch (JSONException e) { | |
e.printStackStrace(); | |
Log.e(TAG, "Unable to get request"); | |
dataOutputStream.flush(); | |
} | |
} | |
} catch (IOException e) { | |
e.printStackStrace(); | |
} finally { | |
if (socket != null) { | |
try { | |
socket.close(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
if (dataInputStream != null) { | |
try { | |
dataInputStream.close(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
if (dataOutputStream != null) { | |
try { | |
dataOutputStream.close(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
} | |
} | |
} | |
} |
This is how we connected Two Android devices over WiFi without having to enter any IP Address as it gets cumbersome.
We got a lot of help from Android-er.
We plan to create a bi-directional connection and data service between Client and Server and both respond with appropriate data based on the query.
P.S. Configuring and testing all this took a lot of time, but these small things make me really happy. More post coming soon.
Playing around with Android UI
Articles focusing on Android UI - playing around with ViewPagers, CoordinatorLayout, meaningful motions and animations, implementing difficult customized views, etc.