I have a simple echo-server in Java:
int portNumber = 4444;
try (
ServerSocket serverSocket =
new ServerSocket(Integer.parseInt(args[0]));
Socket clientSocket = serverSocket.accept();
PrintWriter out =
new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
) {
String inputLine;
while ((inputLine = in.readLine()) != null) {
out.println(inputLine);
System.out.println(inputLine);
}
} catch (IOException e) {
System.out.println("Exception caught when trying to listen on port "
+ portNumber + " or listening for a connection");
System.out.println(e.getMessage());
}
and a simple golang client:
func main() {
fmt.Println("start client")
conn, err := net.Dial("tcp", "localhost:4444")
if err != nil {
log.Fatal("Connection error", err)
}
conn.Write([]byte("hello world"))
conn.Close()
fmt.Println("done")
}
When I start the server and then run the client, the server echo's "hello world" as expected but then the server exits/terminates.
Q. How do I prevent this Java termination and force the server to continually wait for more client requests?
When the client terminates, the readLine on server side will result in the end of the stream. So if you want the server to continuously listen for new connections the simply put the above server code in a endless loop.
e.g.
while (true) {
// above code
}
For a play application that would be adequate.
Related
I'm looking for a way to establish an HTTP Request via java to ensure the server is alive.
for example I want to scan ip addresses range 192.168.1.1-255 and print a log with the living server.,
I want to setTimeOut for 3Seconds when the HTTP response is delayed for some reason.
I have tried to do it this way:
try {
Socket s = new Socket(InetAddress.getByName("192.168.1.2"), 80);
s.setSoTimeout(3 * 1000);
PrintWriter pw = new PrintWriter(s.getOutputStream());
pw.println("GET / HTTP/1.1");
pw.println("Host: stackoverflow.com");
pw.println("");
pw.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String t;
while ((t = br.readLine()) != null) System.out.println(t);
br.close();
} catch (SocketTimeoutException e) {
System.out.println("Server is dead.");
} catch (ConnectException e) {
System.out.println("Server is dead.");
}
But it's seem to be not waiting at all when the request is taking longer than 3000millis.
Thanks!
I think you confused the different timeouts. If you want to abort the connection attempt after three seconds without any response, then you should establish the connection as follows:
Socket clientSocket = new Socket();
clientSocket.connect(new InetSocketAddress(target, 80), 3 * 1000);
where target is any IP address. The following line essentially set the timeout value for reading/waiting for the inputstream -after the connection was established. So it has not effect on establishing the connection itself. However, after the connection was established it would interrupt the "read inputstream" step after three seconds (by throwing an exception).
clientSocket.setSoTimeout(3 * 1000);
However, if you want to limit also the time for reading the inputstream without throwing an exception, then you need a costum solution:
Is it possible to read from a InputStream with a timeout?
The following running example worked very well in my local network. It tried to connect for at most three seconds and detected all running webservers.
public class Main {
public static void main(String[] args) {
String net = "192.168.168."; // this is my local network
for (int i = 1; i < 255; i++) { // we scan the range 1-255
String target = net + i;
System.out.println("Try to connect to: " + target);
try {
Socket clientSocket = new Socket();
// we try to establish a connection, timeout is three seconds
clientSocket.connect(new InetSocketAddress(target, 80), 3 * 1000);
// talk to the server
PrintWriter out = new PrintWriter(clientSocket.getOutputStream());
out.println("GET / HTTP/1.1");
out.println("Host: stackoverflow.com");
out.println("");
out.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String t;
while ((t = br.readLine()) != null) System.out.println(t); // We print the answer of the server
br.close();
clientSocket.close();
// server seems to be alive
System.out.println("> Server is alive");
} catch (SocketTimeoutException | ConnectException e) {
System.out.println("> Server is dead");
} catch (Exception e) { // This is not nice but this is also just a demo
e.printStackTrace();
}
}
}
}
Output (excerpt):
Try to connect to: 192.168.168.1
> Server is dead
Try to connect to: 192.168.168.2
> Server is dead
...
Try to connect to: 192.168.168.23
(answer of the server)
> Server is alive
...
I have a server socket connection in a Java application. I have it connected to a client socket connection in a matlab script. I can get it to work fine if I start the server then start the client. But if I disconnect the client and try to start the client again it won't reconnect. How can I detect a disconnection on the socket on the server side, in order to reset the connections.
Server Side (Java)
boolean ss = false;
while(true){
try{
ServerSocket listener = new ServerSocket(9090);
Socket socket = listener.accept();
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
while(!ss){
if (files != null){
for( int i = 0; i < files.length; i++ )
{
out.println(files[i].getCanonicalPath());
}
files = null;
}
ss = out.checkError();
}
}
catch( IOException e)
{}
finally{
listener.close();
socket.close();
}
}
client side (matlab)
function filenameclient
tcpipClient = tcpip('127.0.0.1',9090,'NetworkRole','Client');
set(tcpipClient,'InputBufferSize',7688);
set(tcpipClient,'Timeout',30);
fopen(tcpipClient);
while(1)
if (tcpipClient.BytesAvailable > 0)
rawData = fread(tcpipClient,tcpipClient.BytesAvailable);
fprintf('FileName: %s\n',rawData);
end
end
fclose(tcpipClient);
end
I know the fclose never gets called, but I call it from the console after the stop the matlab client.
I wrote code can send a message to server. Problem is if I capture communication in Wireshark my string message sent from my application looks like this:
hello - 1 packet
If I check the same message sent from Telnet cmd terminal message looks like this:
h - 1 packet
e - 1 packet
l - 1 packet
l - 1 packet
o - 1 packet
So finally it sent entire string by character. Server can read the message from cmd Telnet terminal and reply but can't read the message sent from my application. Is there some way how can I send string like this? I'm not programming server. I'm programming only client side so it's important server has to able read the message correctly. Thanks a lot!
PrintWriter out;
BufferedReader in;
public void run() {
// TODO Auto-generated method stub
try {
InetAddress serverAddr = InetAddress.getByName(hostname);
// create a socket to make the connection with the server
socket = new Socket(serverAddr, port);
Log.i("Terminal", "Socket connecting");
try {
// send the message to the server
out = new PrintWriter(
new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream())), true);
Log.i("Terminal", "Connected.");
// receive the message which the server sends back
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
}catch...
}catch...
}
//send code
public void sendMessage(String message) {
if (out != null && !out.checkError()) {
out.println(message);
out.flush();
Log.i("Terminal", "Message sent.");
}
}
Why not just send each character separately?
Something like this:
public void sendMessage(String message) {
for (String ch : message.split(""))
sendPacket(ch);
sendPacket("\r\n");
}
public void sendPacket(String payload) {
if (out != null && !out.checkError()) {
out.print(payload);
out.flush();
Log.i("Terminal", "Message sent.");
}
}
You said everything was working fine, but if you do run in to issues with packet coalescing in the future you can disable the Nagle algorithm by adding this line:
socket.setTcpNoDelay(true);
right after this one:
socket = new Socket(serverAddr, port);
I'm currently attempting to code my first client>server system to transmit packets containing strings back and forth through a network. However I'm having a problem in that the following is happening:
The client sends message to the server, the server receives the message, processes the message, and then supposedly sends a reply to the client, but the client never receives this message and hangs waiting for a response from the server. Here is the code:
SERVER:
public static void handlePackets() throws Exception {
String clientSentence;
String returnToClient;
ServerSocket welcomeSocket = new ServerSocket(1337);
System.out.println("Packet receiver initialized!");
while (run) {
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
clientSentence = inFromClient.readLine();
System.out.println("Received Packet: " + clientSentence);
System.out.println("Compiling return to client.");
returnToClient = "";
if (clientSentence.startsWith("Handshake-")) {
returnToClient = handleHandShake(clientSentence);
}
outToClient.writeBytes(returnToClient);
System.out.println("Sent client response " + returnToClient);
}
welcomeSocket.close();
}
CLIENT:
public static String sendTCP(String host, String content) {
try {
System.out.println("Packet sender sending TCP packet " + content);
String serverResponse;
Socket clientSocket = new Socket(host, 1337);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
outToServer.writeBytes(content + '\n');
System.out.println("Send data to sever. Awaiting response.");
serverResponse = inFromServer.readLine();
clientSocket.close();
System.out.println("Server response received " + serverResponse + " result was returned to caller.");
return serverResponse;
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
The client is calling readLine() but the server isn't writing a line, just bytes, so the client is waiting forever for the line terminator. Append '\n' to the server's reply. Also the server should close the accepted socket once it's finished with it. Do this by closing whatever writer or output stream you have wrapped around it, not by closing the socket itself.
You should use BufferedOutputStream instead of DataOutputStream. It will work for simple data as is but you are liable to charset problems if you don't fix it sooner or later. In general you should always use symmetric input and output streams or readers.
1) You should close or flush outToServer / outToClient
2) When you read with BufferedReader you should write with BufferedWriter, not DataOutputStream
I am building a small chat application in which client A wants to send something to client C with server B in between. First of all is this a correct approach for the problem??. I am able to send and receive data to and from a server but it is limited to only the client.For example if Client A sends data to server B and client C is sending data to server B then i can send data back to A and C just like an echo server. But what i want is to forward data coming from Client A to Client C via server B.
The following is the server code:
public class Server {
public static void main(String[] args) {
int port = 666; //random port number
try {
ServerSocket ss = new ServerSocket(port);
System.out.println("Waiting for a client....");
System.out.println("Got a client :) ... Finally, someone saw me through all the cover!");
System.out.println();
while(true) {
Socket socket = ss.accept();
SSocket sSocket = new SSocket(socket);
Thread t = new Thread(sSocket);
t.start();
System.out.println("Socket Stack Size-----"+socketMap.size());
}
}
catch (Exception e) { }
}
}
class SSocket implements Runnable {
private Socket socket;
public SSocket(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try {
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
DataInputStream dIn = new DataInputStream(in);
DataOutputStream dOut = new DataOutputStream(out);
String line = null;
while (true) {
line = dIn.readUTF();
System.out.println("Recievd the line----" + line);
dOut.writeUTF(line + " Comming back from the server");
dOut.flush();
System.out.println("waiting for the next line....");
}
}
catch (Exception e) { }
}
}
The client code is :
public class Client {
public static void main(String[] args) {
int serverPort = 666;
try {
InetAddress inetAdd = InetAddress.getByName("127.0.0.1");
Socket socket = new Socket(inetAdd, serverPort);
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
DataInputStream dIn = new DataInputStream(in);
DataOutputStream dOut = new DataOutputStream(out);
BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Type in something and press enter. Will send it to the server and tell ya what it thinks.");
System.out.println();
String line = null;
while (true) {
line = keyboard.readLine();
System.out.println("Wrinting Something on the server");
dOut.writeUTF(line);
dOut.flush();
line = dIn.readUTF();
System.out.println("Line Sent back by the server---" + line);
}
}
catch (Exception e) { }
}
}
When your clients connect to the server, your server creates a Socket for it, here it is Socket socket = ss.accept();, your socket variable will be holding that client.
now if you just keep adding your client socket to a arraylist in your while loop, you will have a list of clients actively connected with your server like:
after the accept:
clients = new ArrayList<DataOutputStream>();
Socket socket = ss.accept();
os = new DataOutputStream(socket.getOutputStream());
clients.add(os);
Now as you have all the clients in that clients arraylist, you can loop through it, or with some protocol define which client should i send the data after reading.
Iterator<DataOutputStream> it = clients.iterator();
while ((message = reader.readLine()) != null) { //reading
while (it.hasNext()) {
try {
DataOutputStream oss = it.next();
oss.write(message);//writing
oss.flush();
}
catch (Exception e) { }
}
}
This will loop through all the available clients in the arraylist and will send to all. you can define ways to send to only some.
For example:
maintain a ActiveClients arraylist and with some GUI interaction may be or maybe, define what all clients you want to send the message.
Then add just those clients outputStreams to ActiveClients
ActiveClients.add(clients.get(2));
or remove them, if you don't want them.
ActiveClients.remove(clients.get(2));
and now just loop through this arraylist to send the data as above.
You can create message queue for each client:
Client A sends message 'Hi' with address Client C to server B.
Server B receives message and adds it to message queue of client C.
Thread in server B which communicates with client C check message queue, retrieve message and sends it to client C.
Client C receives message.
If I am not mistaken, you must be having a problem with receiving a message from the Server or SSocket class. What happens with your code is that when you send a message from the client to the server the Server class receives your messages also gives an echo of the message in the client. However, when you send a message from the Server class, you don't get any messages in the Client Class.
To get this to work, you would have to modify your code in the following fashion:
SSocket Class
String line = null;
while (true) {
line = dIn.readUTF();
System.out.println("Recievd the line----" + line);
dOut.writeUTF(line + " Comming back from the server");
dOut.flush();
System.out.println("waiting for the next line....");
}
You should add these lines:
String Line2 = take.nextLine(); //The user types a message for the client
dOut.writeUTF(Line2 + " Comming back from the server"); //The message is sent to the client
Replace the while loop with this one and it will work fine.
while (true) {
line = dIn.readUTF(); //Takes the msg from the client
System.out.println("Recievd the line----" + line); //Prints the taken message
String Line2 = take.nextLine(); //The user types a message for the client
dOut.writeUTF(Line2 + " Comming back from the server"); //The message is sent to the client
dOut.flush();
System.out.println("waiting for the next line....");
}