I am trying to connect from a android emulator to a application on my desktop and send a line of text.
My app is able to connect to the server, but when ever i try to read data its always null
Server application running on my desktop:
ServerSocket ss = new ServerSocket(9001);
Socket cs = ss.accept();
if (cs.isConnected()) {
System.out.println("Client connected.");
}
BufferedReader reader = new BufferedReader(new InputStreamReader(cs.getInputStream()));
String str = reader.readLine();
System.out.println("Data:" + str);
Client application running in android app emulator:
InetAddress addr = InetAddress.getByName("10.0.2.2");
Socket socket = new Socket(addr, 9001);
if (socket.isConnected()) {
Log.d("APP", "socket connected");
}
PrintWriter pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
String str = "this is a sample";
pw.write(str);
I can see that the isConnected function of the socket on both the client and server turns true.
But the Data printed on the server is always null.
Thanks
Try adding a flush call after the 'pw.write(str)' statement:
pw.flush();
Related
I'm doing a financial messaging integration as follows:
A server has an interface listening for requests from a client socket on a specific IP and port
Server sends a response for every request, back to the client socket
Also, server sends requests to the same client socket
The following is working perfectly:
The client socket (Socket object of Java IO) successfully sends requests to the server interface
The client socket successfully receives response for every request
try {
Socket clientSocket = new Socket("example.com", 8888);
BufferedWriter output = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
output.write(data);
output.flush();
BufferedReader input = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
// Read responses or new request from input
} catch (IOException e) {
e.printStackTrace();
}
The client socket is supposed to receive any request from the server - the same way it's receiving responses from the same sever. However, when a server initiates a request to the client socket, the request is never received. However, we can trace the traffic from the tcpdump on the client environment.
How can I make the client socket listen to requests from the server, and not just responses?
Update
It might help to clarify something on this integration:
a. The 'server' in this case is a third party system, with it's integration rules
b. My client socket posts message to the server (above)
c. My implementation listens to responses and requests from the third party system server, either by creating my own server socket (ruled out), or using the very client socket I'm sending with (the solution I was seeking)
This is a very common mistake, you are writing a message without writing "\n" (end line identifier) at the end so no messages will be read. To fix this use PrintWriter with println.
That will send a line to the other socket.
Here is an example of a thread-per-client model of a server
//create a new server socket with the port as a parameter, this will bind it to the specified port: 6000
ServerSocket server = new ServerSocket(6000);
System.out.println("Binded");
//create a while loop accepting sockets
while(true)
{
//accept a socket
Socket client = server.accept();
System.out.println("Client has connected");
//create a new thread for this socket
new Thread(() ->
{
try
{
/*
create a print writer so you can write a line, not only a message like BufferedWriter does,
if for some reason you still want to use BufferedWriter use
writer.write(message + "\n");
*/
PrintWriter writer = new PrintWriter(new OutputStreamWriter(client.getOutputStream()));
//Create a new reader
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
System.out.println("Waiting for requests...");
//create a while loop reading requests (lines)
String request;
while((request = reader.readLine()) != null)
{
System.out.println("Received message: " + request);
//here find the correct response and return it, I just sent a message, replace it with the correct response
writer.println("Hello there! How are you today?");
//flush, flushing will write the data to the client
writer.flush();
}
} catch(IOException e)
{
//print an exception if it occurred, if an exception occurrs its most likely just a disconnection exception
e.printStackTrace();
}
}).start();
}
and here is an example of a client
//connect to the server at "localhost" on port 6000
Socket client = new Socket("localhost", 6000);
System.out.println("Connected");
/*
create a print writer so you can write a line, not only a message like BufferedWriter does,
if for some reason you still want to use BufferedWriter use
writer.write(message + "\n");
*/
PrintWriter writer = new PrintWriter(new OutputStreamWriter(client.getOutputStream()));
//Create a new reader
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
//write a request
writer.println("Hi there!");
//flush, flushing will write the data to the server
writer.flush();
System.out.println("Written");
System.out.println("Waiting for responses...");
//create a while loop reading responses (lines)
//you may want to do this while loop in another thread
String response;
while((response = reader.readLine()) != null)
{
System.out.println("Received response: " + response);
}
Also if this is involved with financial information I recommend using TLS (SSL).
You don't have to worry Java already has it implemented and has made it easy to use, here is an example of a server
//create a new SSL server socket with the port as a parameter, this will bind it to the specified port: 6000
//you create it by getting the default SSLServerSocketFactory which will create a new SSLServerSocket
//you need to cast it since it actually returns ServerSocket but SSLServerSocket extends ServerSocket and this returns SSLServerSocket so it is safe
SSLServerSocket server = (SSLServerSocket) SSLServerSocketFactory.getDefault().createServerSocket(6000);
System.out.println("Binded");
//set the enabled ciphersuites, until you buy a certificate set only to ciphersuites with "anon" more info on ciphersuites on https://en.wikipedia.org/wiki/Cipher_suite
server.setEnabledCipherSuites(new String[]{"TLS_ECDH_anon_WITH_AES_256_CBC_SHA"});
//create a while loop accepting sockets
while(true)
{
//accept a socket a SSLSocket
SSLSocket client = (SSLSocket) server.accept();
System.out.println("Client has connected");
//create a new thread for this socket
new Thread(() ->
{
try
{
//begin a handshake more info about handshakes in https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_7.1.0/com.ibm.mq.doc/sy10660_.htm
client.startHandshake();
/*
create a print writer so you can write a line, not only a message like BufferedWriter does,
if for some reason you still want to use BufferedWriter use
writer.write(message + "\n");
*/
PrintWriter writer = new PrintWriter(new OutputStreamWriter(client.getOutputStream()));
//Create a new reader
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
System.out.println("Waiting for requests...");
//create a while loop reading requests (lines)
String request;
while((request = reader.readLine()) != null)
{
System.out.println("Received message: " + request);
//here find the correct response and return it, I just sent a message, replace it with the correct response
writer.println("Hello there! How are you today?");
//flush, flushing will write the data to the client
writer.flush();
}
} catch(IOException e)
{
//print an exception if it occurred, if an exception occurrs its most likely just a disconnection exception
e.printStackTrace();
}
}).start();
}
And here is an example of a client
//connect to the server at "localhost" on port 6000
//you create a SSLSocket by getting the default SSLSocketFactory which will create a new SSLSocket
//you need to cast it since it actually returns Socket but SSLSocket extends Socket and this returns SSLSocket so it is safe
SSLSocket client = (SSLSocket) SSLSocketFactory.getDefault().createSocket("localhost", 6000);
System.out.println("Connected");
//set the enabled ciphersuites to everything supported so the server can decide the ciphersuite, you can modify this to specified ciphersuites
client.setEnabledCipherSuites(client.getSupportedCipherSuites());
//begin a handshake more info about handshakes in https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_7.1.0/com.ibm.mq.doc/sy10660_.htm
client.startHandshake();
/*
create a print writer so you can write a line, not only a message like BufferedWriter does,
if for some reason you still want to use BufferedWriter use
writer.write(message + "\n");
*/
PrintWriter writer = new PrintWriter(new OutputStreamWriter(client.getOutputStream()));
//Create a new reader
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
//write a request
writer.println("Hi there!");
//flush, flushing will write the data to the server
writer.flush();
System.out.println("Written");
System.out.println("Waiting for responses...");
//create a while loop reading responses (lines)
//you may want to do this while loop in another thread
String response;
while((response = reader.readLine()) != null)
{
System.out.println("Received response: " + response);
}
I am creating and testing a simple TCP server on an Android emulator.
I use a simple Java client program to try to connect to the server running on the emulator. I attempt to send a simple string like "hello world".
I think the connection between the client and server is successfully initialized; however, data is not routed to the Android device.
The server thread blocks at line clientSentence = inFromClient.readLine(); and the client thread blocks at String serverResponse = inFromServer.readLine();.
I have port forwarded local host port 6100 to AVD virtual port 7100 as per Google docs with ADB
adb -s emulator-5554 forward tcp:6100 tcp:7100
Here is Java class TCPTestClient
public class TCPTestClient
{
public static void main(String argv[]) throws Exception
{
String sentenceToServer = "hello server";
System.out.println("initializing socket");
Socket clientSocket = new Socket("127.0.0.1", 6100);
System.out.println("socket initialized");
System.out.println("getting output stream to server");
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
System.out.println("found output stream to server");
System.out.println("getting input stream from server");
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
System.out.println("found input stream from server");
System.out.println("writing sentence to server");
outToServer.writeBytes(sentenceToServer );
System.out.println("sentence written");
System.out.println("waiting for sentence response from server");
String serverResponse = inFromServer.readLine();
System.out.println("serverResponse = "+serverResponse);
System.out.println("socket closed");
clientSocket.close();
}
}
Here is Android app method initTcpTestServer()
private void initTcpTestServer()
{
Log.d("TAG", "initTcpTestServer()");
try
{
String clientSentence;
ServerSocket welcomeSocket = new ServerSocket(7100);
while ( true )
{
Log.d("TAG", "looking for socket");
Socket connectionSocket = welcomeSocket.accept();
Log.d("TAG", "socket accepted");
Log.d("TAG", "getting input stream");
BufferedReader inFromClient = new BufferedReader(
new InputStreamReader(connectionSocket.getInputStream()));
Log.d("TAG", "input stream found");
Log.d("TAG", "getting output stream");
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
Log.d("TAG", "output stream found");
Log.d("TAG", "reading input stream");
clientSentence = inFromClient.readLine();
Log.d("TAG", "input stream read");
Log.d("TAG", "input = " + clientSentence);
Log.d("TAG", "writing output back to client");
outToClient.writeBytes(clientSentence);
Log.d("TAG", "output written back to client");
}
}
catch ( IOException e )
{
e.printStackTrace();
}
}
If I initialize the TCP server first I get output
initTcpTestServer()
looking for socket
After initializing the TCP server and then initializing the TCP client I get from the server
getting input stream
input stream found
getting output stream
output stream found
reading input stream
and from the client
initializing socket
socket initialized
getting output stream to server
found output stream to server
getting input stream from server
found input stream from server
writing sentence to server
sentence written
waiting for sentence response from server
so it appears that the socket is established, but the server blocks at line
clientSentence = inFromClient.readLine();
and the client blocks at
String serverResponse = inFromServer.readLine();
becuase the client has written the data, but the server has never received it, and the client is hanging waiting for the server's reponse.
Thank you Scary Wombat. Adding a "\n" at the end of the String resulted in a successful TCP message to the server. A TCP server can indeed be set up on an Android emulator by configuring port forwarding on the AVD virtual router with ADB. However, I have only testing this on local host.
I have been looking through the multitudes of explanation of basic Java Socket use, and have constructed the following basic code for my own Server/Client echo pair. However, there is some hangup in the client code that I cannot find for the life of me. Perhaps someone else can spot it?
// Server Code:
try (ServerSocket serverSocket = new ServerSocket(22222);
Socket cSocket = serverSocket.accept();
PrintWriter out = new PrintWriter(cSocket.getOutputStream());
BufferedReader in = new BufferedReader(
new InputStreamReader(cSocket.getInputStream()))) {
System.out.println("Client connected: " + cSocket.getInetAddress().getHostAddress());
// console DOES print ^this line and correct IP when client is run.
String inLine;
while (true) {
inLine = in.readLine();
out.println(inLine);
if (inLine.equals("exit")) break;
}
// client code
try (Socket socket = new Socket("localhost", 22222);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedReader consoleIn = new BufferedReader(new InputStreamReader(System.in));) {
String userIn;
while (true) {
System.out.print("Client> ");
userIn = consoleIn.readLine();
out.println(userIn); // code hangs here.
out.flush();
System.out.println("Server> " + in.readLine());
if (userIn.equals("exit")) break;
}
It isn't blocking there. It's blocking in the readLine() from the server. Try a flush() after the println() in the server.
I've been working on a simple Android TCP Server, so I can connect from a TCP Client and pass data back and forth.
I am encountering an weird problem, my android phone creates the TCP Socket, and I am able to connect to it via Hercules utility (A TCP client). The connection goes through, however the program is still blocking at the ServerSocket.accept() method.
Could anyone shed some light on this issue? Here is my java function.
public void TcpServer()
{
try
{
Socket s = null;
ServerSocket ss = null;
System.out.println("TCP Server Starting");
ss = new ServerSocket(27015);
s = ss.accept();
System.out.println("New connection! Yay");
BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
String incomingMsg = input.readLine();
System.out.println("Received: " + incomingMsg);
}
catch (Exception e)
{
}
}
I have a code like the one below
Server side:
Socket socket = server-client conn socket
try
{
BufferedReader inFromNode = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
PrintWriter outToNode = new PrintWriter(socket.getOutputStream(), true);
String data = inFromNode.readLine().toString();
String data1 = inFromNode.readLine().toString();
String data2 = inFromNode.readLine().toString();
outToNode .println("Hi");
}
Client side:
Socket socket = server-client conn socket
try
{
BufferedReader inFromNode = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
PrintWriter outToNode = new PrintWriter(socket.getOutputStream(), true);
outToNode .println("Hi");
outToNode .println("Hi");
outToNode .println("Hi");
String data = inFromNode.readLine().toString();
}
The problem is the client side code is waiting for the reply from the server. I am sure the server side has sent it(I tried placing logs after the send on the server side and they got printed.) Am I overlooking on something here? Is the code wrong in any way?
Try closing the PrintWriter and the Socket when writing to client finishes from Server. This should ideally fix your problem.