Java Server to Android Client: Cannot receive TCP packets - java

I'm trying to write a Java server so that an Android client can send a string to it, and the server would reply with its own string. The first part of this works, where the client sends a string to the server, but the server sending a message to the does not work: the packet makes it out of the server, but the Android client does not pick it up. Does anyone have suggestions on how to fix this?
This entire process worked previously on a Python server, but I am changing to Java because of library support (Java has better support for NAT traversal)
Server (Java):
public class TCPServer implements Runnable {
private Thread t = null;
#Override
public void run() {
// TODO Auto-generated method stub
String receive;
String response = "1||2||3||4\n";
ServerSocket tcpServer = null;
Socket tcpClient = null;
try {
tcpServer = new ServerSocket(4999);
System.out.println(" TCP open for connections");
while(true) {
tcpClient = tcpServer.accept();
BufferedReader inStream = new BufferedReader(new InputStreamReader(tcpClient.getInputStream()));
receive = inStream.readLine();
System.out.println("Server <<< " + receive);
DataOutputStream outStream = new DataOutputStream(tcpClient.getOutputStream());
outStream.write(response.getBytes("UTF-8"));
outStream.flush();
System.out.println("Server >>> " + response);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("IOException: " + e.toString());
} finally {
if (tcpServer != null) {
try {
tcpServer.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("IOException: " + e.toString());
}
}
if (tcpClient != null) {
try {
tcpClient.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("IOException: " + e.toString());
}
}
}
}
public void start() {
// TODO Auto-generated method stub
if(t == null) {
t = new Thread(this);
t.start();
System.out.println("Start TCP Server");
}
}
}
Client (Android):
public class AsyncTCPSend extends AsyncTask<Void, Void, Void> {
String address = "";
String message = "";
String response = "";
AsyncTCPSend(String addr, String mes) {
address = addr;
message = mes + "\n";
}
#Override
protected Void doInBackground(Void... params) {
Socket socket = null;
try {
socket = new Socket(address, 4999);
socket.getOutputStream().write(message.getBytes());
ByteArrayOutputStream writeBuffer = new ByteArrayOutputStream(1024);
byte[] buffer = new byte[1024];
int bytesRead;
InputStream writeIn = socket.getInputStream();
while((bytesRead = writeIn.read(buffer)) != -1) {
writeBuffer.write(buffer,0,bytesRead);
response += writeBuffer.toString("UTF-8");
}
} catch (UnknownHostException e){
e.printStackTrace();
response = "Unknown HostException: " + e.toString();
System.out.println(response);
} catch (IOException e) {
response = "IOException: " + e.toString();
System.out.println(response);
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
#Override
protected void onPostExecute(Void result) {
recieve.setText(response);
super.onPostExecute(result);
}
}

I don't know why you would call an InputStream 'writeIn', but the problem is that the client is reading the socket until end of stream, and the server is never closing the accepted socket, so end of stream never occurs.

Related

Java socket can client can not read the data

The client send a message, then the server receives the message and response the message. I don't know why the client can not read the response. If I remove the read part in client, the server can get the message. However for the following code, nothing work. Also I tried the flush(), it still doesn't work.
For client
public void run() {
try (Socket echoSocket = new Socket(HOSTNAME, Integer.parseInt(PORTNUMBER));
DataOutputStream dOut = new DataOutputStream(echoSocket.getOutputStream());
DataInputStream dIn = new DataInputStream(echoSocket.getInputStream());
) {
while (true) {
command = UI.commandQueue.take()
dOut.writeInt(Message.toByteArray(command).length);
dOut.write(Message.toByteArray(command));
int length;
while((length = dIn.readInt()) != 0) {
if (length > 0){
byte[] messagebyte = new byte[length];
dIn.readFully(messagebyte, 0, messagebyte.length);
try {
msg = Message.fromByteArray(messagebyte);
testDisplay(msg);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
testDisplay(msg);
}
}
}
}catch (UnknownHostException e) {
UI.display("Don't know about host " + HOSTNAME);
} catch (IOException e) {
UI.display("Couldn't get I/O for the connection to " + HOSTNAME);
}
}
For server
public void run() {
try (ServerSocket serverSocket = new ServerSocket(Integer.parseInt(PORT_NUMBER));
Socket clientSocket = serverSocket.accept();
DataOutputStream dOut = new DataOutputStream(clientSocket.getOutputStream());
DataInputStream dIn = new DataInputStream(clientSocket.getInputStream());) {
int length;
while ((length = dIn.readInt()) != 0) {
if (length > 0) {
byte[] messagebyte = new byte[length];
dIn.readFully(messagebyte, 0, messagebyte.length); // read the
// message
Message msg;
try {
msg = Message.fromByteArray(messagebyte);
testDisplay(msg);
dOut.writeInt(Message.toByteArray(msg).length);
dOut.write(Message.toByteArray(msg));
UI.display("ack sent");
} catch (Exception e) {
// TODO Auto-generated catch block
UI.display(e.getMessage());
}
}
}
} catch (IOException e) {
UI.display(
"Exception caught when trying to listen on port " + PORT_NUMBER + " or listening for a connection");
UI.display(e.getMessage());
}
}
Your server is echoing one response per request, but your client is trying to read more than one response per request, which it will never get, so it blocks.

Android client/server application - proper way to receive messages continously

I'm trying to make a client/server application using an Android phone as a client using AsyncTask to send messages from UI.
I've written some very basic implementation just to test the connection and the way that messages are received / sent and I found a very big problem.
The client part seems to work fine..from my perspective. But the server part is the problem. I can't make the server reading and displaying messages countinously from the client.
I tried something like while(line = (in.readLine()) != null) {} but it doesn't seems to work.
After I sent my first word from the client, the server reads null and it stops.
Can someone show me a proper way to keep the server running while the client is not sending nothing?
I'd like to avoid using while(true) if it's not 100% necessary.
Here is the implementation until now:
Server:
public class SocketServerThread extends Thread {
private static final Logger log = Logger.getLogger(SocketServerThread.class);
private static final int SERVER_PORT_NUMBER = 5000;
#Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(SERVER_PORT_NUMBER);
serverSocket.setReuseAddress(true);
log.info("Waiting for connection...");
Socket clientSocket = serverSocket.accept();
log.info("Connected! Receiving message...");
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
try {
while (true) {
String line = in.readLine();
if (line != null) {
log.info(line);
}
}
} catch (Exception e) {
log.error("Unexpected exception while sending / receiving messages.");
e.printStackTrace();
} finally {
in.close();
clientSocket.close();
serverSocket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
Client:
public class MyAsyncTask extends AsyncTask<String, Integer, String> {
private static final String TAG = "MyAsyncTask";
private static final String SERVER_IP_ADDRESS = "10.0.2.2";
private static final int SERVER_PORT_NUMBER = 5000;
private PrintWriter out;
#Override
protected String doInBackground(String... params) {
String message = "";
try {
InetAddress address = InetAddress.getByName(SERVER_IP_ADDRESS);
Log.d(TAG, "Connecting...");
Socket socket = new Socket(address, SERVER_PORT_NUMBER);
try {
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
Log.d(TAG, "I/O created");
message = params[0];
if (!message.equals("stop")) {
sendMessage(message);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
out.flush();
out.close();
socket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
return message;
}
private void sendMessage(String message) {
if (out != null && !out.checkError()) {
out.println(message);
out.flush();
Log.d(TAG, "Sent message: " + message);
}
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
Log.d(TAG, "onPostExecute(), s: " + s);
}
Thank you.
The problem is that your BufferedReader only read the first input stream. In order to receive the text after that, you have to re-read the input stream. I do it by recreating the socket when I am done reading, so that I can read next coming data. I am using the following code in my app. You can use this
private ServerSocket serverSocket;
public static final int SERVERPORT = 5000;
Thread serverThread = null;
public void startSocketServer(){
this.serverThread = new Thread(new ServerThread());
this.serverThread.start();
}
public void stopSocket(){
if(serverSocket != null){
try{
serverSocket.close();
}
catch (IOException e){
e.printStackTrace();
}
}
}
class ServerThread implements Runnable {
public void run() {
Socket socket = null;
try {
Log.wtf(TAG,"Socket: New Socket");
serverSocket = new ServerSocket(SERVERPORT);
if(serverSocket == null){
runOnUiThread(new Runnable() {
#Override
public void run() {
startSocketServer();
}
});
return;
}
while (!Thread.currentThread().isInterrupted() && !serverSocket.isClosed()) {
try {
socket = serverSocket.accept();
Log.wtf(TAG,"Socket: Accepting");
CommunicationThread commThread = new CommunicationThread(socket);
new Thread(commThread).start();
} catch (IOException e) {
Log.wtf(TAG,"Socket: Error");
e.printStackTrace();
}
if(Thread.currentThread().isInterrupted()){
Log.wtf(TAG, "Thread Interrupted");
}
if(serverSocket.isClosed()){
Log.wtf(TAG, "serverSocket closed");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class CommunicationThread implements Runnable {
private Socket clientSocket;
public CommunicationThread(Socket clientSocket) {
this.clientSocket = clientSocket;
log.info("Connected! Receiving message...");
try {
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
try {
while (true) {
String line = in.readLine();
if (line != null) {
log.info(line);
}
else
break;//This will exit the loop and refresh the socket for next data
}
} catch (Exception e) {
log.error("Unexpected exception while sending / receiving messages.");
e.printStackTrace();
}
finally {
in.close();
clientSocket.close();
}
refreshSocket();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void refreshSocket(){
runOnUiThread(new Runnable() {
#Override
public void run() {
stopSocket();
startSocketServer();
}
});
}
Just call startSocketServer() to start the server socket in your code.

how many users can handle on android client, pc java server with socket?

I made a simple app works with socket to transfer data between client and server over local network,
Server java codes:
try {
serverSocket = new ServerSocket(8888);
System.out.println("Listening :8888");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while (true) {
try {
socket = serverSocket.accept();
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream = new DataOutputStream(
socket.getOutputStream());
System.out.println("ip: " + socket.getInetAddress());
String message = dataInputStream.readUTF();
// System.out.println("message: " + dataInputStream.readUTF());
try {
JSONObject jObj = new JSONObject(message);
String flag = jObj.getString("flag");
if (flag.equals("request")) {
String request = jObj.getString("request");
if (request.equals("getGroup"))
dataOutputStream.writeUTF(getGroup());
else if (request.equals("getFood")) {
String groupID = jObj.getString("groupID");
dataOutputStream.writeUTF(getFood(groupID));
}
}
} catch (JSONException | IOException e) {
e.printStackTrace();
}
// dataOutputStream.writeUTF("Hello!");
} catch (IOException e) {
e.printStackTrace();
} 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();
}
}
}
}
and android client codes:
class Load extends AsyncTask<String, String, String> {
String response;
#Override
protected void onPreExecute() {
super.onPreExecute();
}
protected String doInBackground(String... args) {
Socket socket = null;
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
try {
socket = new Socket("192.168.1.106", 8888);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream.writeUTF(utils.getGroup());
response = dataInputStream.readUTF();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataOutputStream != null) {
try {
dataOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
protected void onPostExecute(String file_url) {
showGroup(response);
}
}
How many clients this can handle?
Is there a better solution?
How many clients this can handle?
Basically your code is an iterative server. There’s one big loop, and in each pass through the loop a single connection is completely processed.
A: So in this sense it can handle only one client at a time.
If you want to suport more than one client at a time your server should service multiple clients simultaneously through the use of threads (one thread per each client connection).
The basic flow of logic in such a server is this:
while (true) {
accept a connection;
create a thread to deal with the client;
}
Please refer to the following tutorial for a full explanation and even some code example.
Is there a better solution?
In the Android side, as pointed out in my comment based in the answer here. Using AsyncTask for HTTP communications can have some drawbacks like:
You cannot cancel a request during execution.
The patterns of using AsyncTask also commonly leak a reference to an Activity...
A: A library like OkHttp can apply as a more robust alternative.

Server not sending messages to the clients connected to it

I have created a chat server which is multi threaded and as and when the clients connect it initiates a separate thread for them to communicate. The problem is the my server is not broadcasting messages received from one client to all the other clients connected and I simply do not know how to implement it.
Following is my code, feel free to edit:
The serverclass:
ArrayList<ServerThread> clientlist = new ArrayList();
Hashtable clientList = new Hashtable();
private static ArrayList<PrintWriter> writers = new ArrayList<PrintWriter>();
public ChatServer(JTextField jtfA, JTextField jtfB, JTextArea jtaA, JTextArea tapane3) {
// TODO Auto-generated constructor stub
address= jtfA;
GETPORT=jtfB;
PORT=Integer.parseInt(jtfB.getText());
displaytext=jtaA;
clientside=tapane3;
}
public void run() {
// TODO Auto-generated method stub
try {
InetAddress ad=InetAddress.getLocalHost();
String ip=ad.toString();
address.setText(string);
address.setEditable(false);
System.out.println("Server IP is: " + ad);
ss = new ServerSocket (PORT);
Socket cs = null;
while (true)
{
cs=ss.accept();
System.out.println("Connected"+clientlist);
ServerThread handler = new ServerThread(cs,displaytext,clientside,writers);
clientlist.add(handler);
handler.start();
System.out.println(writers);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getActionCommand().equals("DisConnect"))
{
try {
ss.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
The server thread class::
public class ServerThread extends Thread {
Socket client;
JTextArea display;
JTextArea clients;
ServerSocket server;
ArrayList<PrintWriter> writers ;
public ServerThread(Socket cs, JTextArea displaytext, JTextArea clientside, ArrayList<PrintWriter> writers) {
// TODO Auto-generated constructor stub
client=cs;
display=displaytext;
clients=clientside;
this. writers=writers;
}
public void run () {
try{
BufferedReader br = new BufferedReader(
new InputStreamReader(
client.getInputStream()));
PrintWriter pr = new PrintWriter(
new OutputStreamWriter(
client.getOutputStream()));
String clientMsg="";
boolean all;
do {
//read msg from client
clientMsg = br.readLine();
//display.setText(clientMsg);
System.out.println("Server Received: " + clientMsg);
pr.println(clientMsg);
display.append(clientMsg+"\n");
clients.append(clientMsg+"\n");
pr.flush();
} while((all=br.readLine() != null));
br.close();
pr.close();
while (true) {
String input = br.readLine();
if (input == null) {
return;
}
for (PrintWriter writer : writers) {
writer.println("MESSAGE " + ": " + input);
}
}}
catch (UnknownHostException uhe){
System.out.println("Server issue");
}
catch (IOException ioe){
System.out.println("Server Error IO");
}
catch (Exception e){
System.out.println("Server Error General");
}}
}
Faulty do/while loop. You're throwing away every second line, and not detecting end of stream correctly. It should be:
while ((line = br.readLine()) != null)

Program stop working when try to read input stream

I have a Java Server and one(or more) Android Clients. For now I want them to communicate simply with strings. When i write from android I can get the data in Java Server, but when I try to get the answer from server the Android application stop working. The codes is reported below:
Java Server:
public class Server {
private static int port=12346, maxConnections=0;
// Listen for incoming connections and handle them
public static void main(String[] args) {
int i=0;
try{
ServerSocket listener = new ServerSocket(port);
Socket server;
while((i++ < maxConnections) || (maxConnections == 0)){
doComms connection;
server = listener.accept();
String end = server.getInetAddress().toString();
System.out.println("\n"+end+"\n");
doComms conn_c= new doComms(server);
Thread t = new Thread(conn_c);
t.start();
}
} catch (IOException ioe) {
System.out.println("IOException on socket listen: " + ioe);
ioe.printStackTrace();
}
}
}
class doComms implements Runnable {
private Socket server;
private String line,input;
public doComms(Socket server) {
this.server=server;
}
#SuppressWarnings("deprecation")
public void run () {
input="";
try {
// Get input from the client
DataInputStream in = new DataInputStream (server.getInputStream());
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(server.getOutputStream())),
true);
while((line = in.readLine()) != null && !line.equals(".")) {
input=input + line;
}
JOptionPane.showMessageDialog(null, input);
out.println("Enviado");
server.close();
} catch (IOException ioe) {
System.out.println("IOException on socket listen: " + ioe);
ioe.printStackTrace();
}
}
And Android client's code (it's called every time a button is pressed inside onClick method):
public String enviaMensagem(){
String resposta="";
new Thread(new ClientThread()).start();
Socket socket = null;
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
try {
socket = new Socket(ip, port);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream.writeUTF(input.getText().toString());
resposta = dataInputStream.readUTF();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
if (socket != null){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (dataOutputStream != null){
try {
dataOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (dataInputStream != null){
try {
dataInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return resposta;
}
You are using an unsorted mixture of readUTF(), writeUTF(), readLine(), etc. They're not all interoperable. Settle on one of them. If you use writeUTF() you must use readUTF() at the other end. If you use readLine() you must write lines at the other end, with a line terminator such as \r\n or \n.

Categories

Resources