How to make my web server wait? - java

I'm coding a little web server, which is returning Hello using 3000 port:
import java.net.ServerSocket;
import java.net.Socket;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
public class HttpServer {
public static void main(String[] args) throws Throwable {
//http://localhost:3000
ServerSocket ss = new ServerSocket(3000);
while (true) {
//Waiting for socket
Socket s = ss.accept();
System.out.println("Client accepted");
//The main process
new SocketProcessor(s,ss).start();
}
}
private static class SocketProcessor implements Runnable {
private Thread t;
private Socket s;
private ServerSocket ss;
private InputStream is;
private OutputStream os;
private SocketProcessor(Socket s,ServerSocket ss) throws Throwable {
t = new Thread(this, "Server Thread");
this.ss=ss;
this.s = s;
this.is = s.getInputStream();
this.os = s.getOutputStream();
}
public void run() {
try {
readInputHeaders();
writeResponse("<html><body><h1>Hello</h1></body></html>");
} catch (Throwable t) {
/*do nothing*/
} finally {
try {
s.close();
} catch (Throwable t) {
}
}
System.out.println("Client processing finished");
}
public void start()
{
t.start();
}
private void writeResponse(String s) throws Throwable {
String response = "HTTP/1.1 200 OK\r\n" +
"Server: Server\r\n" +
"Content-Type: text/html\r\n" +
"Content-Length: " + s.length() + "\r\n" +
"Connection: close\r\n\r\n";
String result = response + s;
os.write(result.getBytes());
os.flush();
}
private void readInputHeaders() throws Throwable {
BufferedReader br = new BufferedReader(new InputStreamReader(is));
while(true) {
String s = br.readLine();
System.out.println(s);
if(s == null || s.trim().length() == 0) {
break;
}
}
}
}
}
I want to make my server wait for second before response. I was trying to use something like this:
readInputHeaders();
t.wait(1000);
writeResponse("<html><body><h1>Hello</h1></body></html>");
But my browser says ERR_EMPTY_RESPONSE

Call Thread.sleep(1000) in the run method of the SocketProcessor.
The method wait is not the right one to call for your purpose.
See also:
Thread.sleep JavaDoc
The methods wait, notify, notifyAll are defined on java.lang.Object
and are used for synchronization between threads. They are not generally
for the purpose of making a thread sleep for a certain amount of time.

Related

How to use existing Objects in an overwritten run() Method?

I'm a beginner in programming and do strugle a bit.
So I'm building a TCP peer to peer Chat and that requires me to divide the tasks -> Threads.
So I want to built a Thread for the "writing" part of that connection (Scanner, DataOutputStream etc.) In order to do that i implemented Runnable and that forces me to write my Thread in the overwritten run() method.
Now I have a bit of a problem, because in Order to send my messages out to the "other end (another client) I need the "socket.getOutputStream" but I cant use it in the run() method and i dont know how to fix this problem, sitting already a week on this problem. Any ideas ?
public class ClientHorcher implements Runnable {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(11111);
System.out.println("Waiting For Connection:-");
Socket socket = serverSocket.accept();
Scanner scanner = new Scanner(System.in);
DataInputStream datenRein = new DataInputStream(socket.getInputStream());
DataOutputStream datenRaus = new DataOutputStream(socket.getOutputStream());
String nickname;
System.out.print("Gib einen Nickname ein: ");
nickname = scanner.nextLine();
while (true) {
String vonMsg = datenRein.readUTF(in);
System.out.println("Client:-" + vonMsg);
if (vonMsg.equals("exit")) {
System.out.println("Beenden!!!");
datenRein.close();
datenRaus.close();
scanner.close();
socket.close();
serverSocket.close();
System.exit(0);
}
System.out.print(nickname + ":-");
String zuMsg = scanner.nextLine();
datenRaus.writeUTF(zuMsg);
if (zuMsg.equals("exit")) {
System.out.println("Quiting!!!");
datenRein.close();
datenRaus.close();
scanner.close();
socket.close();
serverSocket.close();
System.exit(0);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
}
}`
`public class ClientVerbinder implements Runnable {
public static void main(String[] args) {
try {
Socket socket = new Socket("Localhost", 11111);
System.out.println("Connected");
Scanner scanner = new Scanner(System.in);
DataInputStream datenRein = new DataInputStream(socket.getInputStream());
DataOutputStream datenRaus = new DataOutputStream(socket.getOutputStream());
String nickname;
System.out.print("Gib einen Nickname ein: ");
nickname = scanner.nextLine();
while (true) {
System.out.print(nickname+":-");
String zuMsg = scanner.nextLine();
datenRaus.writeUTF(zuMsg);
if (zuMsg.equals("exit")) {
System.out.println("Beenden!!!");
datenRein.close();
datenRaus.close();
scanner.close();
socket.close();
System.exit(0);
}
String vonMsg = datenRein.readUTF();
System.out.println("CLient"+":-" + vonMsg);
if (vonMsg.equals("exit")) {
System.out.println("Quiting!!!");
datenRein.close();
datenRaus.close();
scanner.close();
socket.close();
System.exit(0);
}
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
}
}
Multiple possibilities.
Use static variables. Normally you would not do that, but because your code is all-static, you could
Use member variables in an OO-style code.
If you wanted to do it properly, you'd split the server into two parts:
The ServerSocket listener that only listens to connections (Socket connectionToClient = ss.accept), and whenever a connection comes in, creates a new
ClientHandler, passes in the Socket, and the ClientHandler then starts its own thread internally
This way, the ClientHandler has all the data it needs (again as member variables) and can work on its own concerns (aka 'separation of concerns).
Update
This is what I created. Really simple.
Start Server
Start 1st client
Start 2nd client
In any client, type message
Other client receives it
Classes:
SimpleServer
package stackoverflow.simplemtserver;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.LinkedBlockingDeque;
public class SimpleServer { // make it closeable and close sockets if this is not standalone
public static void main(final String[] args) throws IOException {
final int port = 7623;
new SimpleServer(port);
}
final LinkedBlockingDeque<SimpleServerClientHandler> clientHandlers = new LinkedBlockingDeque<>();
private final ServerSocket mServerSocket;
public SimpleServer(final int pPort) throws IOException {
mServerSocket = new ServerSocket(pPort);
final Thread m = new Thread(() -> runLoop(), getClass().getSimpleName() + " Main Loop");
m.start();
}
private void runLoop() {
while (true) {
try {
System.out.println("Server waiting for connection...");
#SuppressWarnings("resource") final Socket cs = mServerSocket.accept(); // do NOT close the socket here, no try-resource, will interrupt threaded communication!
final SimpleServerClientHandler ch = new SimpleServerClientHandler(this, cs);
clientHandlers.add(ch);
System.out.println("Connection accepted, handler started. Handlers active: " + clientHandlers.size());
} catch (final IOException e) {
// handle this how you need it
e.printStackTrace();
}
}
}
public void signOffClientHandler(final SimpleServerClientHandler pClientHandler) {
clientHandlers.remove(pClientHandler); // we could also accommplish this using stack trace to avoid access from outside, but this is the easier solution
}
public void spreadMessageToClients(final String pMessageFromClient, final SimpleServerClientHandler pSimpleServerClientHandler) {
for (final SimpleServerClientHandler ch : clientHandlers) {
if (ch != pSimpleServerClientHandler) ch.relayMessageToClient(pMessageFromClient); // we can work with identity == and != here
}
}
}
SimpleServerClientHandler
package stackoverflow.simplemtserver;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
public class SimpleServerClientHandler {
private final SimpleServer mParentServer;
private final Socket mClientSocket;
private final DataInputStream mDIS;
private final DataOutputStream mDOS;
public SimpleServerClientHandler(final SimpleServer pSimpleServer, final Socket pCS) throws IOException {
mParentServer = pSimpleServer;
mClientSocket = pCS;
mDIS = new DataInputStream(mClientSocket.getInputStream());
mDOS = new DataOutputStream(mClientSocket.getOutputStream());
final Thread t = new Thread(() -> runComms(), getClass().getSimpleName() + " Comms Loop");
t.setDaemon(true); // threads now stop once server stops. this is NOT a soft exit
t.start();
}
private void runComms() {
try {
try {
while (true) {
// do all your logic here, work with DIS and DOS
final String messageFromClient = mDIS.readUTF();
if (messageFromClient == null) break;
if (!messageFromClient.startsWith("*")) mParentServer.spreadMessageToClients(messageFromClient, this);
}
} catch (final Exception e) {
// TODO: handle exception
}
} finally {
try {
mClientSocket.close(); // also closes DataIn/Out
} catch (final IOException e) { /* ignore */ }
mParentServer.signOffClientHandler(this);
}
}
public void relayMessageToClient(final String pMessageFromClient) {
try {
mDOS.writeUTF("*" + pMessageFromClient);
} catch (final IOException e) {
// ignore unless needed otherwise
}
}
}
SimpleClient
package stackoverflow.simplemtserver;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Scanner;
public class SimpleClient {
public static void main(final String[] args) throws UnknownHostException, IOException {
final String hostname = "localhost";
final int port = 7623;
try (final Socket s = new Socket(hostname, port);
final DataInputStream dis = new DataInputStream(s.getInputStream());
final DataOutputStream dos = new DataOutputStream(s.getOutputStream());
final Scanner scanner = new Scanner(System.in);) {
final Thread t = new Thread(() -> runListenerLoop(dis), SimpleClient.class.getSimpleName() + " Reader Thread");
t.setDaemon(true);
t.start();
while (true) {
System.out.println("Enter message:");
System.out.flush();
final String msg = scanner.nextLine();
if (msg == null) break;
System.out.println("Spreading message: " + msg);
dos.writeUTF(msg);
}
}
}
private static void runListenerLoop(final DataInputStream pDis) {
while (true) {
try {
System.out.println("Waiting for incoming messages...");
final String msg = pDis.readUTF();
System.out.println("Received: " + msg);
} catch (final SocketException e) {
// if ("java.net.SocketException: Connection reset".equals(e.getMessage()))
break;
} catch (final IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
From here on, there's now more ways you can extend this client/server communication:
use opcodes (read/write int constants or enums before data) to distinguish for special operations and/or messages (like this here puts an asterisk in front of the string to prevent re-re-laying the same message indefinitely over the network)
read multiple strings for user, message, additional options
implement this is a user friendly UI so you dont have to use console I/O
Update 2
The pure peer-to-peer solution is this one.
If the app is run without params, it goes into listening mode, waiting for a connection.
If the app is run with one arguments, it interprets it as listening port and also goes into listening mode.
If the app is un with [hostname] [port] arguments, it will try to connect there
Example:
start first app without arguments (listening)
start second app with arguments "localhost 7642" (connecting)
both apps will now
connect,
then set up I/O resources,
then start the listening thread for incoming messages
then go into the read-keyboard-and-write-to-socket loop
now you can type a message in one of the apps, the other one will receive it
p2p code:
package stackoverflow.simplemtserver;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Scanner;
public class SimplePeerToPeerClient {
static public final int DEFAULT_PORT = 7642;
public static void main(final String[] args) throws UnknownHostException, IOException {
if (args.length == 0) {
System.out.println("Waiting on default port " + DEFAULT_PORT);
waitForConnection(DEFAULT_PORT);
} else if (args.length == 1) {
final int port = Integer.parseInt(args[0]);
System.out.println("Waiting on port " + port);
waitForConnection(port);
} else if (args.length == 2) {
final String hostName = args[0];
final int port = Integer.parseInt(args[1]);
System.out.println("Connecting to " + hostName + " on port " + port);
connectToOtherSide(hostName, port);
} else throw new IllegalArgumentException("Invalid amount of argument! Need none (listen) or 2: [hostname] [port] (connect)");
}
private static void waitForConnection(final int pPort) throws IOException {
try (final ServerSocket ss = new ServerSocket(pPort);) {
#SuppressWarnings("resource") final Socket socket = ss.accept(); // will get closed later
startComms(socket);
} // closes ServerSocket after 1st connection
}
private static void connectToOtherSide(final String pHostName, final int pPort) throws UnknownHostException, IOException {
#SuppressWarnings("resource") final Socket socket = new Socket(pHostName, pPort); // will get closed later
startComms(socket);
}
private static void startComms(final Socket pSocket) throws IOException {
try (
final DataInputStream dis = new DataInputStream(pSocket.getInputStream());
final DataOutputStream dos = new DataOutputStream(pSocket.getOutputStream());
final Scanner scanner = new Scanner(System.in);) {
// run the listener loop
final Thread t = new Thread(() -> runListenerLoop(dis), SimpleClient.class.getSimpleName() + " Reader Thread");
t.setDaemon(true);
t.start();
// run my keyboard-input-send loop
while (true) {
System.out.println("Enter message:");
System.out.flush();
final String msg = scanner.nextLine();
if (msg == null) break; // empty input ends client
System.out.println("Spreading message: " + msg);
dos.writeUTF(msg);
}
} finally {
try {
pSocket.close();
} catch (final IOException e) { /* ignore */ }
}
}
private static void runListenerLoop(final DataInputStream pDis) {
while (true) {
try {
System.out.println("Waiting for incoming messages...");
final String msg = pDis.readUTF();
System.out.println("Received: " + msg);
} catch (final SocketException e) {
// if ("java.net.SocketException: Connection reset".equals(e.getMessage()))
break;
} catch (final IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

Java basic concurrent communicator - does not fully accept connection

I want to create simple communicator with one server and few clients who could connect and send data to it. It works fine without any threads, with only one client, but once i try to incorporate concurrency it doesn't work. From client perspective there is some connection, I can send data, but there is no sign of receiving that data on server. Here is the server class:
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;
public class MyServerSocket implements Runnable
{
private ServerSocket serverSocket;
public MyServerSocket() throws Exception
{
Random generator = new Random();
this.serverSocket = new ServerSocket(generator.nextInt(65000 - 60000) + 60000, 50, InetAddress.getByName("192.168.0.105"));
}
public InetAddress getSocketIPAddress()
{
return this.serverSocket.getInetAddress();
}
public int getPort()
{
return this.serverSocket.getLocalPort();
}
public void run()
{
while (true)
{
System.out.println("Running a thread");
try
{
String data = null;
Socket client = this.serverSocket.accept();
String clientAddress = client.getInetAddress().getHostName();
System.out.println("Connection from: " + clientAddress);
System.out.println("Here I am");
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
String message = "";
while ((data = in.readLine()) != null && data.compareToIgnoreCase("quit") != 0)
{
message = ("\r\nMessage from " + clientAddress + ": " + data);
System.out.println(message);
out.write(message);
}
} catch (Exception e)
{
System.out.println("Something went wrong");
} finally
{
try
{
serverSocket.close();
} catch (IOException e)
{
e.printStackTrace();
}
}
}
}
}
Server main:
import java.lang.Thread;
public class Main
{
public static void main(String[] args)
{
try
{
MyServerSocket socket = new MyServerSocket();
Runnable runnable = new MyServerSocket();
System.out.println("Port number: " + socket.getPort() + " IP address: " + socket.getSocketIPAddress());
Thread thread = new Thread(runnable);
thread.start();
}catch (Exception e)
{
e.printStackTrace();
}
}
}
Client class:
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
public class ClientSocket
{
private Socket socket;
private Scanner scanner;
ClientSocket(InetAddress serverAddress, int serverPort) throws Exception
{
this.socket = new Socket(serverAddress, serverPort);
this.scanner = new Scanner(System.in);
}
public void sendData() throws Exception
{
String data;
System.out.println("Please type in the message. If you want to terminate the connection, type Quit");
PrintWriter out = new PrintWriter(this.socket.getOutputStream(), true);
do
{
data = scanner.nextLine();
out.println(data);
out.flush();
}while(data.compareToIgnoreCase("quit") != 0);
out.println();
}
}
Client main:
import java.net.InetAddress;
import java.util.Scanner;
public class Main
{
public static void main(String[] args)
{
Scanner scanner = new Scanner(System.in);
int port;
System.out.println("Provide port at which you will communicate with the server");
port = scanner.nextInt();
try
{
ClientSocket socket1 = new ClientSocket(InetAddress.getByName("192.168.0.105"), port);
socket1.sendData();
}catch(Exception e)
{
System.out.println("Could not connect to the server.");
}
}
}
Server somehow stops its working when is about to accept the client connection, while client works fine and seem to be connected to the server.
In server side, once you accept a client connection, you should new a thread to process this connection:
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;
public class MyServerSocket implements Runnable {
private ServerSocket serverSocket;
public MyServerSocket() throws Exception {
Random generator = new Random();
this.serverSocket = new ServerSocket(generator.nextInt(65000 - 60000) + 60000, 50, InetAddress.getByName("192.168.0.105"));
}
public InetAddress getSocketIPAddress() {
return this.serverSocket.getInetAddress();
}
public int getPort() {
return this.serverSocket.getLocalPort();
}
public void run() {
while (true) {
System.out.println("Running a thread");
try(Socket client = this.serverSocket.accept()) {
// new thread to process this client
new Thread(() -> {
try {
String data = null;
String clientAddress = client.getInetAddress().getHostName();
System.out.println("Connection from: " + clientAddress);
System.out.println("Here I am");
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
String message = "";
while (true) {
if (!((data = in.readLine()) != null && data.compareToIgnoreCase("quit") != 0)) break;
message = ("\r\nMessage from " + clientAddress + ": " + data);
System.out.println(message);
out.write(message);
}
} catch (IOException e) {
System.out.println("Something went wrong");
}
}).start();
} catch (Exception e) {
System.out.println("Something went wrong");
}
}
}
}
Ok, somehow I solved that problem, but still I need to understand how does it work:
Accepting connection inside try block, without finally block (nor try with resources) so socket is opened all the time.
Modified main method so there is no threads or runnable objects at all in it. The whole process is done within the class:
Code:
public class Main
{
public static void main(String[] args)
{
try
{
MyServerSocket socket = new MyServerSocket();
System.out.println("Port number: " + socket.getPort() + " IP address: " + socket.getSocketIPAddress());
socket.run();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
If anyone could point me out mistakes that are still in this final version of code I'll be grateful.

java server is receiving from 1 client only and not from the 2nd

Good day, I'm trying to create a Client/Server chat, that the 1st client send message to server and the server send it to client 2 and vice versa, but the server is just receiving from 1st client only and not from 2nd.
and also, how can i send messages from client 1 to 2 & vice versa
package s;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
public class Client
{
public static void main(String[] args) throws IOException, Throwable
{
Socket s;
BufferedReader in;
PrintWriter out;
Scanner sc = new Scanner(System.in);
s = new Socket(InetAddress.getLocalHost(),9000);
System.out.println("Connection pending");
in = new BufferedReader (new InputStreamReader(s.getInputStream()));
out = new PrintWriter(s.getOutputStream());
String msg = in.readLine();
System.out.println(msg);
while(msg!="")
{
msg = sc.nextLine();
out.println(msg+"\n");
out.flush();
}
s.close();
sc.close();
}
}
=============================================
package s;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class TClient extends Thread
{
private int num;
private Socket s;
private BufferedReader in;
private PrintWriter out;
public Socket getS()
{
return s;
}
public BufferedReader getIn()
{
return in;
}
public PrintWriter getOut()
{
return out;
}
public TClient(Socket s,int num) throws IOException
{
this.s = s;
this.setNum(num);
System.out.println("Client"+num);
out = new PrintWriter(s.getOutputStream());
in = new BufferedReader (new InputStreamReader(s.getInputStream()));
out.println("Connected"+num+"\n");
out.flush();
}
public void run()
{
while(true)
{
try
{
String msg="";
msg = in.readLine();
System.out.println(msg);
if (msg.equals(".")) break;
}
catch (IOException e)
{
}
}
try
{
s.close();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public int getNum()
{
return num;
}
public void setNum(int num)
{
this.num = num;
}
}
========================================================
package s;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server
{
public static void main(String[] args)
{
ServerSocket ss ;
Socket s = null ;
int nb_clients = 0;
String msg = "";
TClient[] connexions = new TClient[2];
try
{
ss = new ServerSocket(9000);
System.out.println("Server is listening in:"+ss.getLocalPort());
boolean continu = false;
while(!continu)
{
s = ss.accept();
connexions[nb_clients] = new TClient(s,nb_clients+1);
connexions[nb_clients].start();
nb_clients++;
if (nb_clients>=2) continu=true;
}
System.out.println("Clients connected");
s.close();
ss.close();
}
catch(IOException e)
{
}
}
}
========================================
and the output of each terminal is :
Server is listening in:9000
Client1
Client2
Clients connected
and the output of the 2 clients are :
Connection pending
Connected1
Connection pending
Connected2
if i write a message from 1 & 2 to the server, the server output will be like this:
Server is listening in:9000
Client1
Client2
Clients connected
111111111111111111111111111111111111
================================================================
UPDATE :
i changed a condition in server
if (nb_clients>2) continu=true;
and now i can recieve from both clients, now i have to know how i make them communicate between the clients
Solution for two clients.
Sending messages from one client to another client.
The server will have to marshall the messages between the clients.
public class Server
{
static TClient[] connexions = new TClient[2];
public static void send(int clientNum, String message) {
TClient t = connexions[clientNum];
if(t != null) {
t.getOut().println(message);
t.getOut().flush();
}
}
}
In TClient added:
public void sendMessage(String message) {
int client = (getNum()-1)==1 ? 0:1;
Server.send(client, message);
System.out.printf("Sending message(%s) to client:%d from client:%d%n",message,client,getNum());
}
which I added a call to inside your while loop.
In Client I used another thread for receiving message from the server called ReceiveMessageThread:
public class Client
{
public static void main(String[] args) throws IOException, Throwable
{
Socket s;
BufferedReader in;
PrintWriter out;
Scanner sc = new Scanner(System.in);
s = new Socket(InetAddress.getLocalHost(), 9000);
System.out.println("Connection pending");
in = new BufferedReader(new InputStreamReader(s.getInputStream()));
out = new PrintWriter(s.getOutputStream());
ReceiveMessageThread thread = new ReceiveMessageThread(in);
String msg = in.readLine();
System.out.println(msg);
thread.start();
while (msg != "")
{
msg = sc.nextLine();
out.println(msg + "\n");
out.flush();
}
s.close();
sc.close();
}
public static class ReceiveMessageThread extends Thread
{
private BufferedReader in;
public ReceiveMessageThread(BufferedReader in)
{
this.in = in;
}
public void run()
{
while (true)
{
try
{
String message = readMessage(in);
if (message != null && !message.equals(""))
System.out.println(message);
} catch (IOException ie)
{
ie.printStackTrace();
}
}
}
public String readMessage(BufferedReader in) throws IOException
{
String msgreceived = "";
String readValue = "";
while (in.ready())
{
readValue = in.readLine();
if (readValue != null)
msgreceived += readValue;
}
return msgreceived;
}
}
}
in server i changed :
if (nb_clients>2) continu=true;
and the server reads from different clients.

Try-with-resources closes sockets of spawned childs

I want to write a simple server that listens on a port and spawns new threads for handling new connections.
I attempted to use try-with-resources for accepting new connections but failed because sockets in child threads seem to be closed immediately and I don't understand why.
Here are 2 simplified examples.
a) The working example of the server (without try-with-resources):
package MyTest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class MyServerA implements Runnable {
private int port;
private ServerSocket serverSocket;
public MyServerA(Integer port) {
this.port = port;
}
#Override
public void run() {
try {
serverSocket = new ServerSocket(port);
} catch(IOException ioe) {
System.err.println("error opening socket. " + ioe.getStackTrace());
}
while (true) {
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
ClientServiceThread cliThread = new ClientServiceThread(clientSocket);
cliThread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class ClientServiceThread extends Thread {
private Socket s;
boolean goOn = true;
ClientServiceThread(Socket s) {
this.s = s;
}
public void run() {
BufferedReader in = null;
PrintWriter out = null;
try {
in = new BufferedReader(new InputStreamReader(this.s.getInputStream()));
out = new PrintWriter(new OutputStreamWriter(this.s.getOutputStream()));
while (goOn) {
final String req = in.readLine();
if (req != null) {
System.out.println("got: " + req);
out.println("you said: " + req);
out.flush();
if (req.contains("bye")) {
System.out.println("closing thread");
goOn = false;
}
}
}
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
MyServerA a = new MyServerA(30000);
a.run();
}
}
b) Exactly the same, but with try-with-resources (doesn't work):
package MyTest;
import java.io.BufferedReader;
public class MyServerB implements Runnable {
private int port;
private ServerSocket serverSocket;
public MyServerB(Integer port) {
this.port = port;
}
#Override
public void run() {
try {
serverSocket = new ServerSocket(port);
} catch(IOException ioe) {
System.err.println("error opening socket. " + ioe.getStackTrace());
}
while (true) {
try (Socket clientSocket = serverSocket.accept();) {
ClientServiceThread cliThread = new ClientServiceThread(clientSocket);
cliThread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class ClientServiceThread extends Thread {
private Socket s;
boolean goOn = true;
ClientServiceThread(Socket s) {
this.s = s;
}
public void run() {
BufferedReader in = null;
PrintWriter out = null;
try {
in = new BufferedReader(new InputStreamReader(this.s.getInputStream()));
out = new PrintWriter(new OutputStreamWriter(this.s.getOutputStream()));
while (goOn) {
final String req = in.readLine();
if (req != null) {
System.out.println("got: " + req);
out.println("you said: " + req);
out.flush();
if (req.contains("bye")) {
System.out.println("closing thread");
goOn = false;
}
}
}
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
MyServerB b = new MyServerB(30000);
b.run();
}
}
The example in a) works like expected.
The example in b) accepts a connection but closes it immediately.
Can someone explain to me why and tell me how I do this properly?
The structure
try (resource = ...) {
}
is equivalent to
resource = null;
try {
resource = ...;
} finally {
if (resource != null) {
resource.close();
}
}
That's it. It is just a syntactic sugar, just shorter way to write the same. So, when you put statement Socket clientSocket = serverSocket.accept(); into try-with-resource block you actually close it once you leave the block.
This structure is good when processing of stream is done synchronously, i.e. when you open stream, read or write and close it.
In your case you get the stream and process it in separate thread and therefore cannot close it immediately. Client should decide to close the stream itself. For example when user press button "disconnect" or when server sends special application level command "close connection" or if IOException is thrown.

multithreaded mutisocket program

I want to made a Server Which makes a client and start conversation with him but IOException is occur in Handler's code I couldn't underStand why Br.readLine method throws Exception
Here is code of mine Server project's package's classess and two clients abc, def classes are also
This is code of Server projects classeess...............
package server;
import java.io.IOException;
import java.net.ServerSocket;
public class Server {
private void operate() {
try {
ServerSocket serverSocket = new ServerSocket(2222);
while(true) new Thread(new Handler(serverSocket.accept())).start();
} catch(IOException e){
System.out.println("IOException in operate method of Server");
}
}
public static void main(String[] args) {
new Server().operate();
}
}
package server;
import java.io.*;
import java.net.Socket;
public class Handler implements Runnable {
Handler(Socket s) {
socket = s;
counter++;
}
public void run() {
try {
while(true) System.out.println(new BufferedReader(new InputStreamReader(socket.getInputStream())).readLine()); //This throw the IOExceptionnnnnnnnnnnnnnnnnnnnn...............
} catch(IOException e) {
System.out.println("IOException in "+counter+"'s run method");
}
}
private final Socket socket;
private static int counter =0;
}
Code of First Client ABC...........................
package abc;
import java.net.Socket;
import java.io.*;
public class Abc {
public static void main(String[] args) {
try {
Socket socket = new Socket("localhost",2222);
while(true) new PrintWriter(socket.getOutputStream()).println("HI from Abc");
} catch(IOException e) {
System.out.println("IOException in main ");
}
}
}
Code of Another Client DEf.........................
package def;
import java.io.*;
import java.net.Socket;
public class DEf {
public static void main(String[] args) {
try {
Socket socket = new Socket("localhost",2222);
while(true) new PrintWriter(socket.getOutputStream()).println("HI from Abc");
} catch(IOException e) {
System.out.println("IOException in main ");
}
}
}
Your clients request the output stream repeatedly from the socket using socket.getOutputStream(). Instead, you should invoke this method and create a corresponding writer only once, for example:
Socket socket = new Socket("localhost",2222);
PrintWriter writer = new PrintWriter(socket.getOutputStream());
while(true) {
writer.println("HI from Abc");
...
}
Same with the Handler class - create your buffered reader once.
I have already posted answers on Server-Client Socket Communication. Please have a look.
Java Server with Multiclient communication.
Basic echo server, client-server relationship
Try this code. It might solve you problem.
Handler.java:
Check BufferedReader.ready() before BufferedReader.readLine()
Use single BufferedReader
class Handler implements Runnable {
private BufferedReader reader;
Handler(Socket s) {
socket = s;
counter++;
try {
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
try {
while (socket.isConnected() && !socket.isClosed()) {
if(!reader.ready()){
continue;
}
//System.out.println("ready");
System.out.println(reader.readLine()); // This throw
// the
} // IOExceptionnnnnnnnnnnnnnnnnnnnn...............
} catch (Exception e) {
e.printStackTrace();
System.out.println("IOException in " + counter + "'s run method");
}
}
private final Socket socket;
private static int counter = 0;
}
Abc.java:
Use single PrintWriter
PrintWriter writer = new PrintWriter(socket.getOutputStream());
while (true)
writer.println("HI from Abc");
DEf.java:
Use single PrintWriter
PrintWriter writer = new PrintWriter(socket.getOutputStream());
while (true)
writer.println("HI from Abc");

Categories