I created a java chat application (client and server)
Everything works fine when I'm on my LAN (using LAN IP address of the server into my client).
But when I'm using the Internet address of my server in my client, the strings are sent only when I close the output Data stream of my client (and all the strings are sent at once).
Here's a quick snap of my code (I have port forward from 6791 to 6790 in the example below),
My server (thread):
// this line is actually on my global server class, used below with theServer
ServerSocket svrSocket= new ServerSocket(6790);
//wait for incoming connection
connectionSocket = svrSocket.accept();
connectionSocket.setSoTimeout(10000);
// free the accepting port
svrSocket.close();
//create a new thread to accept future connections (creates a new svrSocket)
theServer.openNewConnection();
//create input stream
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
boolean threadRunning = true);
while (threadRunning) {
//System.out.println("thread: in the while");
try {
Thread.sleep(100);
clientSentence = inFromClient.readLine();
System.out.println(clientSentence);
}
catch...
}
My client:
InetAddress dnsName;
Socket clientSocket;
PrintWriter out;
dnsName = InetAddress.getByName("myAddress.me");
clientSocket = new Socket(dnsName.getHostAddress(), 6791);
Thread.sleep(10);
out = new PrintWriter(clientSocket.getOutputStream(), true );
int i=140;
while (i>130){
try {
out.println(Integer.toString(i));
out.flush();
Thread.sleep(200);
}
catch(Exception e) {
e.printStackTrace();
}
i--;
}
out.flush();
out.close();
clientSocket.close();
I've tried with DataOutStreams, there's nothing to do.
My server will only receive the strings when out.close() is called on client side.
Is there a reason why, over the Internet, the data stream has to be closed for data to be sent? Is there a way around this? Am I doing something wrong?
Related
I would like to run a combination of Dart and Java code, that can communicate with each other.
Therefore I chose to go with sockets, with the server socket written in Java and the client socket written in Dart.
This is the code I wrote:
Server
ServerSocket server = new ServerSocket(12345);
server.setSoTimeout(0);
System.out.println("waiting for connection...");
while (true) {
try {
Socket client = socket.accept();
DataInputStream input = new DataInputStream(client.getInputStream());
DataOutputStream output = new DataOutputStream(client.getOutputStream());
System.out.println("connected to " + client.getLocalSocketAddress() + ".");
while (true) {
output.write(input.readLine());
}
} catch (IOException e) {
System.out.println("disconnected.\n\nwaiting for connection...");
}
}
Client
Socket client = await Socket.connect('localhost', 12345);
client.write('hello there\n');
client.close();
Unfortunately the server does not receive the ping message sent by the client.
By now I suppose, that the problem lies in the Dart code, because when executing a client written in Java worked just fine.
Do you know, how to solve this? If so, please let me know ho. Thank you in advance!
Please note:
As there will never be more than one client at a time, I chose to go with this approach. I am aware, that normally this is no good style.
In the documentation for close() on the Socket class:
NOTE: Writes to the IOSink may be buffered, and may not be flushed by a call to close(). To flush all buffered writes, call flush() before calling close().
https://api.dart.dev/stable/2.7.1/dart-io/Socket/close.html
I do not know why, but it seems that the problem lies in the DataInputStream/DataOutputStream.
Here is what worked:
Server
ServerSocket server = new ServerSocket(12345);
server.setSoTimeout(0);
System.out.println("waiting for connection...");
while (true) {
try {
Socket client = socket.accept();
BufferedWriter output = BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
BufferedReader input = new BufferedReader(new InputStreamReader(client.getInputStream()));
System.out.println("connected to " + client.getLocalSocketAddress() + ".");
while (true) {
output.writeUTF(input.readUTF());
}
} catch (IOException e) {
System.out.println("disconnected.\n\nwaiting for connection...");
}
}
Client
Socket client = await Socket.connect('localhost', 12345);
client.write('hello there\n');
client.close();
This is working for me.
Socket client = socket.accept();
byte[] b = new byte[100];
client.getInputStream().read(b);
System.out.println(new String(b));
hi I have an application that sends text to a device and the device shows it on a display. for transferring data I'm using socket in a AsyncTask class
try {
Socket socket = new Socket(DISPLAY_IP, DISPLAY_PORT);
OutputStream out = socket.getOutputStream();
PrintWriter output = new PrintWriter(out);
output.println(params[0]);
output.flush();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
the problem is I can't read response from socket after sending data. when I'm getting input stream from socket and reading line I'm not getting anything and the device is not showing the sent data from me till I close the application so I think the socket is blocking when I'm doing that
try {
Socket socket = new Socket(DISPLAY_IP, DISPLAY_PORT);
OutputStream out = socket.getOutputStream();
PrintWriter output = new PrintWriter(out);
output.println(params[0]);
output.flush();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String response = bufferedReader.readLine();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
how can I send data and read response from socket?
You are trying to communicate with two (client) Sockets. For communication you must implement on one side a (client) java.net.Socket and on the other a java.net.ServerSocket.
You may read further here.
What are you trying to achieve?
When using InputStream it will get data that came from other side, not the data that you just sent.
And as SirGregg said readLine will hang until the whole line is received.
I have TCP server-client application. It works but sometime something happens. Client connects to server but server says he doesn't accepted him.
Server side code:
while(!stopped){
try {
AcceptClient();
} catch(SocketTimeoutException ex){
continue;
} catch (IOException ex) {
System.err.println("AppServer: Client cannot be accepted.\n"+ex.getMessage()+"\n");
break;
}
...
private void AcceptClient() throws IOException {
clientSocket = serverSocket.accept();
clientSocket.setSoTimeout(200);
out = new ObjectOutputStream(clientSocket.getOutputStream());
in = new ObjectInputStream(clientSocket.getInputStream());
System.out.println("Accepted connection from "+clientSocket.getInetAddress());
}
Client side code:
try {
socket = new Socket(IPAddress, serverPort);
socket.setSoTimeout(5000);
out = new ObjectOutputStream(socket.getOutputStream());
in = new ObjectInputStream(socket.getInputStream());
} catch (IOException e1) {
sendSystemMessage("DISCONNECTED");
sendSystemMessage(e1.getMessage());
return;
}
sendSystemMessage("CONNECTED");
If client connects the message:
Accepted connection from ... appears. But sometimes it doesn't appear
even if client sends message "CONNECTED"
Server is still runing the loop trying to get client and it is catching socketTimeoutException. Client is connected, sends message and waits for response.
I suspect a missing 'flush' inside your client's 'sendSystemMessage()'.
Unfortunately the constructor of ObjectInputStream attempts to read a header from the underlying stream (which is not very intuitive IMHO). So if the client fails to flush the data - the server may remain stuck on the line "in = new ObjectInputStream(socket.getInputStream())"...
As a side note it's usually better for a server to launch a thread per incoming client, but that's just a side remark (plus it obviously depends on requirements).
I found the problem. The communication on my net is too slow so it timeouts in getting inputstream. The solution has two parts. Flushing outputstream before getting inputstream. And set socket timout after streams are initialized.
serverside:
clientSocket = serverSocket.accept();
out = new ObjectOutputStream(clientSocket.getOutputStream());
out.flush()
in = new ObjectInputStream(clientSocket.getInputStream());
clientSocket.setSoTimeout(200);
How to connect to server with different IP address
I really don't know what to do...
Let me explain first.
i have a client and server that works great when sending messages between the two if i am on the same network as my computer.
i have an android device and i would like to wish when ever i am placed far away and when i will click some button it will send message to server even if i am not on the same network.
Client
try {
client = new Socket("IpAddress", 4444);
BufferedReader in = new BufferedReader(
new InputStreamReader(client.getInputStream()));
printlng = new PrintWriter(client.getOutputStream());
printlng.println(mlng);
printlng.flush();
while (true) {
if ((Response= in.readLine()) != null) {
Log.i("Response:", Response);
dlng = Double.valueOf(Response);
System.out.println(dlng);
break;
}
}
Server:
public static void main(String[] args) {
try {
serverSocket = new ServerSocket(4444); // Server socket
} catch (IOException e) {
System.out.println("Could not listen on port: 4444");
}
System.out.println("Server started. Listening to the port 4444");
while (true) {
try {
clientSocket = serverSocket.accept(); // accept the client
inputStreamReader = new InputStreamReader(
clientSocket.getInputStream());
bufferedReader = new BufferedReader(inputStreamReader); // get
// the
// client
PrintWriter out = new PrintWriter(
clientSocket.getOutputStream(), true);
InputStream inputStream = new ByteArrayInputStream(
bufferedReader.readLine().getBytes(
Charset.forName("UTF-8")));
BufferedReader bufferedReader2 = new BufferedReader(
new InputStreamReader(inputStream));
String output = bufferedReader2.readLine();
System.out.println(output.toString());
out.println(output.toString());
out.flush();
out.close();
inputStreamReader.close();
clientSocket.close();
} catch (IOException ex) {
System.out.println("Problem in message reading");
}
}
}
You have to find out the external/internet ip address of the pc where your server is running on. You can do that on that pc with http://whatismyip.com. Use the obtained ip in your client. But before it really can work you have to configure the router where your pc is connected to to forward the used port to the lan ip address of your pc.
If everything works fine when you are on the same LAN : the problem is probably coming from some firewall rule not accepting connection on port 4444 when coming from a non local IP.
So, either change the port of the server (if not used yet, port 80 is probably a good choice since there is more chance that connections will be allowed), either change your firewall rules.
I'm building a Java client application which needs to send a message to a server and receive a response afterwards. I can send the message successfully, the problem is that I can't get the response because I get an IO exception ("Socked is closed") when trying to read the 'BufferedReader'.
This is my code, so far:
public class MyClass {
/**
* #param args the command line arguments
*/
#SuppressWarnings("empty-statement")
public static void main(String[] args) {
JSONObject j = new JSONObject();
try {
j.put("comando", 1);
j.put("versao", 1);
j.put("senha", "c4ca4238a0b923820dcc509a6f75849b");
j.put("usuario", "1");
j.put("deviceId", "1");
} catch (JSONException ex) {
System.out.println("JSON Exception reached");
}
String LoginString = "{comando':1,'versao':1,'senha':'c4ca4238a0b923820dcc509a6f75849b','usuario':'1','deviceId':'1'}";
try {
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
Socket clientSocket = new Socket("10.1.1.12", 3333);
System.out.println("Connected to the server successfully");
PrintWriter outToServer = new PrintWriter(clientSocket.getOutputStream(),true);
outToServer.println(j.toString());
outToServer.close();
System.out.println("TO SERVER: " + j.toString());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String resposta = inFromServer.readLine();
System.out.println("FROM SERVER: " + resposta);
clientSocket.close();
} catch (UnknownHostException ex) {
System.out.println("Could not connect to the server [Unknown exception]");
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
}
I know that the socket is being closed because of the OutToServer.close() but closing the stream is the only way to send the message. How should I approach this situation?
flush() is not the case when it comes with new PrintWriter(, true).
The real problem is that you are closing the PrintWriter outToServer which wraps the underlying InputStream, again, came from the Socket.
When you close the outToServer you're closing the whole socket.
You have to use Socket#shutdownOutput().
You don't even have to close the output if you want to keep the socket's in/out channels for further communications.
flush() when you are done with any writeXXX. Those writeXXX practically don't mean you sent those bytes and characters to other side of the socket.
You may have to close the output, and output only, to signal the server that you sent all you had to send. This is really a matter of the server-side socket's desire.
final Socket socket = new Socket(...);
try {
final PrintStream out = new PrintStream(socket.getOutputStream());
// write here
out.flush(); // this is important.
socket.shutdownOutput(); // half closing
// socket is still alive
// read input here
} finally {
socket.close();
}
Try to call outToServer.flush()
That will try to flush the data from the buffer, although it still not guarantees that it will be sent.