I am currently coding a simple TCP chat client-server application which works with sockets. A client connects to the server and as soon as it gets accepted, a new worker thread is created to listen for client input. Connecting to the sever (localhost at port 8818) works fine, but as soon as the worker thread starts listening for more client input after the login a java.net.SocketException: Connection reset is thrown (see stack trace below). I am aware that one possible source of this exception can be a socket that hasn't been closed properly or forcefully by either the server or the client. Therefore, my assumption is that I am not handling the closing of my client socket properly which causes the connection to reset.
What I would like to achieve:
The worker listens for client input, as long as this is not null, requests (e.g. a simple login) are processed, otherwise, the socket is closed (see code excerpts below). My client receives a 'Login Successful' message from the server indicating that my handleLogin() function works, but instead of closing the socket after receiving no more input from the client, the server seems to just reset, even though clientSocket.close() is issued after the while loop.
Server.java
#Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(serverPort);
while (true) {
// Accept connection(s) from new chat client(s)
System.out.println("SERVER: WAITING TO ACCEPT CLIENT CONNECTIONS ...");
Socket clientSocket = serverSocket.accept();
System.out.println("SERVER: CONNECTION ACCEPTED FROM: " + clientSocket);
// Process client request in separate Thread
WorkerThread worker = new WorkerThread(this, clientSocket);
workerList.add(worker);
worker.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
WorkerThread.java
#Override
public void run() {
try {
handleClientSocket();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void handleLogin(OutputStream outputStream, String[] tokens) throws IOException {
if (tokens.length != 3) {
outputStream.write("LOGIN FAILED!\n".getBytes());
return;
}
// Extract username and password from user input
String username = tokens[1];
String password = tokens[2];
if (username.equals("anna") && password.equals("anna")) {
outputStream.write("Login successful!\n".getBytes());
} else {
outputStream.write("Error logging in!\n".getBytes());
}
}
private void handleClientSocket() throws IOException, InterruptedException {
InputStream inputStream = clientSocket.getInputStream();
this.outputStream = clientSocket.getOutputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line;
// THIS IS WHERE THE EXCEPTION OCCURS AFTER CLIENT HAS LOGGED IN SUCCESSFULLY
while ((line = bufferedReader.readLine()) != null) {
String[] tokens = StringUtils.split(line);
if (tokens.length > 0 && tokens != null) {
String command = tokens[0];
// Evaluate the entered command and handle the request accordingly
if ("login".equalsIgnoreCase(command)) {
handleLogin(outputStream, tokens);
}
// process other commands ...
}
}
clientSocket.close(); // POSSIBLY WORNG WAY OF CLOSING THE CLIENT SOCKET?
}
Client.java
import java.io.*;
import java.net.Socket;
public class Client {
private final String serverName;
private final int serverPort;
private Socket mySocket;
private OutputStream serverOut;
private InputStream serverIn;
public Client(String serverName, int serverPort) {
this.serverName = serverName;
this.serverPort = serverPort;
}
private boolean connect() {
try {
mySocket = new Socket(serverName, serverPort);
serverOut = mySocket.getOutputStream();
serverIn = mySocket.getInputStream();
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
private void login(String username, String password) throws IOException {
String command = "login " + username + " " + password + "\n";
serverOut.write(command.getBytes());
}
public static void main(String[] args) throws IOException {
Client client = new Client("localhost", 8818);
if (client.connect()) {
System.out.println("Connection successful!");
client.login("anna", "anna");
} else {
System.err.println("Connection failed ...");
}
}
}
Stack Trace
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:189)
at java.net.SocketInputStream.read(SocketInputStream.java:121)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:161)
at java.io.BufferedReader.readLine(BufferedReader.java:324)
at java.io.BufferedReader.readLine(BufferedReader.java:389)
at WorkerThread.handleClientSocket(WorkerThread.java:70)
at WorkerThread.run(WorkerThread.java:45)
When I test my server with PUTTY (i.e. by connecting to localhost and then issuing commands in PUTTY's terminal), everything works just fine.
I am still fairly new to socket programming, so I also might have a logic flaw here. Any help will be much appreciated as I really would like to continue this project.
Thanks in advance!
The reason of this exception is that you terminated the client once you connected the server, but the server still read something from the stream. The exception occurs. Here is the code I tested:
while (inputStream.available() != 0) {
line = bufferedReader.readLine();
String[] tokens = StringUtils.split(line);
if (tokens.length > 0 && tokens != null) {
String command = tokens[0];
// Evaluate the entered command and handle the request accordingly
if ("login".equalsIgnoreCase(command)) {
handleLogin(outputStream, tokens);
}
// process other commands ...
}
}
change the condition in while loop to check if the inputstream is still available to read.
Related
I have written a program given below. It accept some data from client & returns success in response. Sometimes it throws connection reset error & due to which some socket connection remain unclose result. Any idea how to handle connection reset error when client code tries to communicate & connection is closed by client automatically?
import java.net.*;
import java.io.*;
import java.util.logging.Level;
import java.util.logging.Logger;
public class tcp_server implements Runnable {
private final Socket server;
private PrintWriter toClient = null;
private BufferedReader fromClient = null;
public tcp_server(Socket s) {
this.server = s;
}
#Override
public void run() {
String name = "";
synchronized (server) {
try {
server.setSoTimeout(6000);
toClient
= new PrintWriter(server.getOutputStream(), true);
fromClient
= new BufferedReader(
new InputStreamReader(server.getInputStream()));
String line = "";
String data = "";
while ((line = fromClient.readLine()) != null) {
data = data + line;
toClient.println("{status:success}");
break;
}
} catch (Exception eb) {
System.out.println("{status:error,Reason:" + eb.getMessage() + "}");
} finally {
// System.out.println("Finally not called if timeout occurs");
if (toClient != null) {
toClient.close();
}
if (fromClient != null) {
try {
fromClient.close();
} catch (IOException ex) {
Logger.getLogger(tcp_server.class.getName()).log(Level.SEVERE, null, ex);
}
}
try {
server.close();
} catch (IOException ex) {
Logger.getLogger(tcp_server.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
public static void main(String[] args) throws IOException {
int serverPort = 40820;
ServerSocket serverSocket = new ServerSocket(serverPort);
synchronized (serverSocket) {
for (;;) {
Socket server = serverSocket.accept();
new Thread(new tcp_server(server)).start();
}
}
}
}
This is better code ... but still with same error "Connection reset" though applied timeout to 60sec
You handle it by closing the connection, of course.
The real question is why did you get it? There are several common causes:
you wrote to a connection that had already been closed by the peer
you closed a connection without reading data that had already arrived in the socket receive buffer. This will reset the peer.
Both of these are application protocol errors that should be fixed. There isn't any point in sending data that won't be read.
I created 2 Java programs with sockets in it. I want the client to send continuous data to the server. But after the message sent to the server, the client keeps sending 'null' value to the server (it happens when I close the socket in client program).
Here is my codes:
import ...
public class MainClient {
private Socket serverSock;
private PrintStream clientOutput;
public static void main(String[] args) {
MainClient client = new MainClient();
client.runClient();
}
public void runClient() {
try {
serverSock = new Socket("127.0.0.1",8282);
clientOutput = new PrintStream(serverSock.getOutputStream());
clientOutput.println("Hello, I'm Connected.");
for (int i=0;i<5;i++) {
clientOutput.println(i + "");
clientOutput.flush();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
// try {
// serverSock.close(); It will keeps sending 'null' data to the server if I use this line.
// } catch (IOException e) {
// e.printStackTrace();
// }
}
}
}
The Server Side:
public class MainServer {
private ServerSocket serverSocket;
private int listenPort = 8282;
private InputStream inps;
private Socket clientSocket;
private BufferedReader clientInput;
private MainServer() {
String clientMsg = "";
try {
serverSocket = new ServerSocket(listenPort);
System.out.println("Server is Listening on " + listenPort);
clientSocket = serverSocket.accept();
clientInput = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
while(clientSocket.isConnected()) {
clientMsg = clientInput.readLine();
System.out.println("Client : " + clientMsg);
}
}catch(IOException ex) {
ex.printStackTrace();
}finally {
try {
clientSocket.close();
} catch (IOException e) {}
}
}
public static void main(String[] args) {
new MainServer();
}
}
I tried to close the OutputStream on the Client side with clientOutput.close(); but it sends nulls to the server after it sends the 0-4 loop.
To make it stop and avoid the client sends null data, i should not insert the serverSock.close(); on the Client, but it will returns SocketException. I wanted the client to send 'Closed' message after its done.
Summary, the output on the server is:
Client: 0
Client: 1
Client: 2
Client: 3
Client: 4
Client: null
Client: null
//And so on..
I think there is something missing on the Client Program, i guess?
Thank you for the help :)
As the comment noted, the client is not sending a null value.
The isConnected() method does not do what you think it does, namely it does not tell you if the socket is currently "connected" to its peer, at least in the way you think it should. isConnected() becomes true as soon as the socket transitions into the connected state, and stays true thereafter, even after the socket is shutdown. See this discussion and others on stackoverflow.
The correct way to determine if the peer has shutdown the connection is to attempt to read from the socket and then examine the result for evidence of closure. Please read the Javadocs for the method you are using, they will tell you what the various return values mean. For the BufferedReader.readLine() method, it says:
Returns:
A String containing the contents of the line, not including
any line-termination characters, or null if the end of the stream has
been reached
Throws:
IOException - If an I/O error occurs
Thus you need to check for a null return value to detect a normal socket closure, and if you receive an IOException that indicates some kind of network anomaly.
Your MainClient() have no problem.
clientSocket.isConnected() function in MainServer() always check the status of the client and which results an infinite loop, so after the message 'client:4', clientInput.readLine() should return 'null'.
So instead of checking the client socket is connected or not you can check the client socket is closed or not using function 'clientSocket.isClosed()'.
replace the while loop in MainServer() with below code,
while(!clientSocket.isClosed()) {
clientMsg = clientInput.readLine();
System.out.println("Client : " + clientMsg);
if(clientMsg.equals("Closed")){
clientSocket.close();
// serverSocket.close();
}
}
this will help you to close the client socket at the time of receiving 'Closed' message from server and this avoid the infinite execution of while loop as well as null statement printing.
The code "serverSocket.close()" help you to close the server socket and you can use this at 'MainServer()' if you need to stop the port listening.
typically the code should be something similar
private MainServer() {
String clientMsg = "";
try {
serverSocket = new ServerSocket(listenPort);
System.out.println("Server is Listening on " + listenPort);
clientSocket = serverSocket.accept();
clientInput = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
while ((clientMsg = clientInput.readLine()) != null) {
if(isTerminationString(clientMsg)) {
break;
}
System.out.println("Client : " + clientMsg);
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
clientSocket.close();
} catch (IOException e) {
}
}
}
boolean isTerminationString(String msg) {
return msg.equals("DONE!");
}
where in isTerminationString you check if the msg is a termination msg, the communication protocol should be shared between the client and the server . i gave the example of sending
a DONE message, but it could more complex than that .
as closing the close method on the socket does not guarantee that the socket on the other part gets closed as well, using the isClosed method might not be effective and results in the same problem you have .
I am trying to open a socket inside a bukkit plugin so i could send data to it using php or node but instead of socket remaining open after one use it just closes and also server does not load before this happens what should i do i am out of ideas.
Main:
public class Main extends JavaPlugin {
public void onEnable() {
saveDefaultConfig();
getConfig().options().copyDefaults(true);
System.out.println("[INFO] Main class loaded.");
start();
}
public void start() {
SocketServer server = new SocketServer();
try {
server.start(getConfig().getInt("port"), getConfig().getString("socket-password"));
System.out.println("[INFO] Main successfully called start.");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Socket server class:
When called this should read information convert it into array check the first item in array and use it as auth code then array should be converted into string and used in Command executor class. This works fine but after one use this just closes
public class SocketServer {
private ServerSocket serverSocket;
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
public void start(int port, String socketpwd) throws IOException {
System.out.println("[INFO] Socket server listening on: " + port);
serverSocket = new ServerSocket(port);
clientSocket = serverSocket.accept();
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
Boolean enabled = true;
try {
// Socket authentication
String message = in.readLine();
String suffix[] = message.split(" ");
System.out.println("Socket auth code used: "+ suffix[0]);
System.out.println("Socket pwd is: " + socketpwd);
if (socketpwd.equals(suffix[0])) {
out.println("Auth sucessfull!");
// do the following command from args here
String command = suffix[1];
int suffixL = suffix.length;
// add arguments to command
for (int i = 2; i < suffixL; i++) {
command = command + " " + suffix[i];
}
// call req exec
System.out.println("[INFO] Socket server contacted Request executor with: " + command);
RequestExecutor.executor(command);
enabled = false;
}
else {
out.println("Unrecognised auth code!");
}
} catch (NullPointerException e) {
System.out.println("Exception prevented!");
}
}
public void stop() throws IOException {
in.close();
out.close();
clientSocket.close();
serverSocket.close();
}
}
Other problem as i mentioned is that bukkit server does not fully load before one request has been made to this socket.
Thank you for your help.
First of all you shouldn't be running a socket like that on the main thread, typically you should be running this on an async task using the Bukkit scheduler.
Then once you open the socket you should create a while loop to continuously poll for a connection and handle the incoming data. Instead what you are doing is opening the socket, reading a line and then dropping the connection.
You want to be doing something similar to
while(true){
Socket socket = serverSocket.accept();
}
See this webpage for some more info.
I managed to setup a server which will accept & manage multiple socket clients.
but now when I try to send a message, the server just doesn't receive anything, yet I do flush the message.
This is the method that's managing the clients:
public void run() {
while(true) {
for (Client c : this.clients) {
try {
if (c.getStream().read() != -1) {
if (c.getInputStream() != null) {
System.out.println("He sent message");
c.sendMessage("hey client");
}
}
} catch (IOException e) {
c.destruct();
this.clients.remove(c); break;
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Client list:
public ArrayList<Client> clients = new ArrayList<Client>(); // client list
And Client object:
public class Client {
private Socket socket;
private int clientId;
private BufferedReader inStream;
private PrintWriter outStream;
private boolean socketAlive = true;
public Client(Socket sock) {
this.socket = sock;
}
public void setup() {
setInputOutputStream();
System.out.println("New connection: " + this.getIpAddress());
this.sendMessage("Successfully connected!");
}
public BufferedReader getStream() {
return this.inStream;
}
public String getInputStream() {
String toReturn = "";
try {
toReturn = this.inStream.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return toReturn;
}
public void destruct() {
try {
this.inStream.close();
this.inStream = null;
this.outStream.close();
this.outStream = null;
System.out.println("Client destruct: " + this.socket.getLocalSocketAddress());
this.socket.close();
this.socket = null;
} catch (IOException e) {
e.printStackTrace();
}
}
public Socket getConnection() {
return this.socket;
}
private void setInputOutputStream() {
try {
inStream = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
outStream = new PrintWriter(this.socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendMessage(String s) {
this.outStream.println(s);
this.outStream.flush();
}
public String getIpAddress() {
return this.socket.getRemoteSocketAddress().toString();
}
}
And the client side (sender) :
public static void main(String[] args) {
try {
System.out.println("Client started");
Socket sock = new Socket("localhost", 43594);
Scanner scanner = new Scanner(System.in);
String input;
PrintWriter out = new PrintWriter(sock.getOutputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(sock.getInputStream()));
while (true) {
input = scanner.nextLine();
if (input != null) {
out.print(input);
out.flush();
}
}
} catch (IOException e) {
System.out.println("Client error");
}
}
Why is my server not receiving anything?
One thing:
If I send message + disconnect, this what the server will log (It looks like it only sends the message upon disconnect or something, well no, it enters the if block only upon it):
Server is successfully running on port 43594
New connection: /127.0.0.1:57102
He sent message
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
at sun.nio.cs.StreamDecoder.read(Unknown Source)
at java.io.InputStreamReader.read(Unknown Source)
at java.io.BufferedReader.fill(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at Client.getInputStream(Client.java:32)
at ClientHandler.run(ClientHandler.java:21)
Client destruct: 0.0.0.0/0.0.0.0:43594
What did I do wrong? how can I fix that
Server (main class)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.*;
import java.util.ArrayList;
public class Server {
private int port = 43594;
public void listen() {
System.out.println("Trying to listen...");
try {
final ServerSocket server = new ServerSocket(port);
// Create new thread to handle clients I/O
ClientHandler handler = new ClientHandler(server);
// START it
handler.start();
System.out.println("Server is successfully running on port " + port);
while (true) {
// New connection found create a new Client object
Client cl = new Client(server.accept());
cl.setup();
// add it to clietns list in the I/O handler
handler.clients.add(cl);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// start up
System.out.println("Starting up..");
// server instance
final Server server = new Server();
// create a new thread for server
new Thread(new Runnable() {
#Override
public void run() {
// listen for new connections
server.listen();
}
}).start();
}
}
The client is sending data and the servers is reading.
I think the problem is in Client.getInputStream
this.inStream.readLine(), it reads a line of text.
From documentation:
"Reads a line of text. A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'), or a carriage return followed immediately by a linefeed."
http://docs.oracle.com/javase/7/docs/api/java/io/BufferedReader.html
If you use read instead, maybe it is going to work. Just use a kind of protocol like sending first 1 or 2 bytes with the length of the message. Or you may send a '\n' from the client.
BTW, the reason for the exception in the server when you send and disconnect in the client side may be due to a TCP fact. The client closed the connection and it probably received a TCP ACK from the server. Then TCP in the client sends a RESET segment. Not so sure though. The server was at this.inStream.readLine() and then it received an exception. Didn't you also received "Connection closed by peer"?
I am not sure why, but I needed to use out.println(input) out.flush() instead of .print() or .write()
I don't have an explanation of why do I need to do that. but it worked.
I think the problem comes from the fact that you've got a list of clients and are trying to manage them with that. I looked up java.net.SocketException: Connection reset, and found this question: What's causing my java.net.SocketException: Connection reset?
The answer to this question comes up with this:
In your case it seems that the connection has been closed by the
server end of the connection. This could be an issue with the request
you are sending or an issue at their end.
This made me think that you aren't holding the connection to the client every time. You store it, and then you lose it, so the message isn't sent. To handle more clients, you might rather want to have a list of IPs, rather than clients, and then you connect when you want to send a message. You can't store the Socket connection. It has to be active. Java (The JVM) has it's own "Garbage Collection" system that'll just kill it.
I am trying to create a simple HTTP web server in Java. I'm just taking this in baby steps so it's super simplistic. I'm trying to make it so I can read simple input from the Client and output anything from the Server when they are both connected.
After searching around on tutorials on websites, this is what I've done so far:
public class Server
{
public static void main(String[] args) throws Exception
{
boolean listening = true;
ServerSocket server = null;
int port = 2222;
try
{
System.out.println("Server binding to port " + port);
server = new ServerSocket(port);
}
catch(Exception e)
{
System.out.println("Error: " + e);
System.exit(1);
}
System.out.println("Server successfully binded to port " + port);
while(listening)
{
System.out.println("Attempting to connect to client");
Socket client = server.accept();
System.out.println("Successfully connected to client");
new ServerThread(client).start() ;
}
server.close();
}
}
public class ServerThread extends Thread
{
private Socket socket = null ;
public ServerThread(Socket s)
{
this.socket = s ;
}
public void run()
{
InputStream in = socket.getInputStream() ;
OutputStream out = socket.getOutputStream() ;
byte [] message, reply;
while((in.read(message))
{
out.write(reply) ;
}
in.close() ;
out.close() ;
socket.close() ;
}
}
It binds and then hangs after attempting to connect to the client. This is because I'm not sure what you do in the while loop in the ServerThread and what you do with the message and reply variables >_< It's been a long time since I've done Java so take it easy on me!
I have only use this kind of server as a "curiosity", to learn new stuff nothing more because you are reinventing the wheel, security reasons etc... I only had to use it once because I had to communicate a server with a JSON code and no server could be installed.
This code needs more work such us creating a new thread for each request, a better RCF HTTP implementation but it works with your ordinary browser.
I hope this helps.
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class MiniPbxManServer extends Thread {
private final int PORT = 2222;
public static void main(String[] args) {
MiniPbxManServer gtp = new MiniPbxManServer();
gtp.start();
}
public void run() {
try {
ServerSocket server = new ServerSocket(PORT);
System.out.println("MiniServer active "+PORT);
boolean shudown = true;
while (shudown) {
Socket socket = server.accept();
InputStream is = socket.getInputStream();
PrintWriter out = new PrintWriter(socket.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String line;
line = in.readLine();
String auxLine = line;
line = "";
// looks for post data
int postDataI = -1;
while ((line = in.readLine()) != null && (line.length() != 0)) {
System.out.println(line);
if (line.indexOf("Content-Length:") > -1) {
postDataI = new Integer(line
.substring(
line.indexOf("Content-Length:") + 16,
line.length())).intValue();
}
}
String postData = "";
for (int i = 0; i < postDataI; i++) {
int intParser = in.read();
postData += (char) intParser;
}
out.println("HTTP/1.0 200 OK");
out.println("Content-Type: text/html; charset=utf-8");
out.println("Server: MINISERVER");
// this blank line signals the end of the headers
out.println("");
// Send the HTML page
out.println("<H1>Welcome to the Mini PbxMan server</H1>");
out.println("<H2>GET->"+auxLine+ "</H2>");
out.println("<H2>Post->"+postData+ "</H2>");
out.println("<form name=\"input\" action=\"imback\" method=\"post\">");
out.println("Username: <input type=\"text\" name=\"user\"><input type=\"submit\" value=\"Submit\"></form>");
//if your get parameter contains shutdown it will shutdown
if(auxLine.indexOf("?shutdown")>-1){
shudown = false;
}
out.close();
socket.close();
}
server.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
url: localhost:2222/whatever
I think you're going the right way at a high level. The difference between what you've got and production systems is that they do their polling for input on a socket is done in a different thread so as not to halt the system while waiting for input.
In fact, one of the configuration parameters for a web server is how many clients (threads) to have up and running.
You should always flush data from the server's output stream. The client response may depend on this:
out.flush();
To check for the end of stream, you could use:
int result = 0;
while ((result = in.read(message)) != -1) {
...
Also your reply message does not appear to be initialized, you probably want to resend the client data initially:
reply = message;
The jdk has a simplistic http server included to build embedded http servers. Take a look at this link.