The Main class:
Main {
public static void main(String[] args) {
final HTTPServer server = new HTTPServer(9999);
server.start();
System.out.println("Server started!");
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
server.stop();
System.out.println("Server stopped!");
}));
}
}
HTTPServer {
// for debug
private static int threadNumber;
private final int port;
private Thread listenThread;
public HTTPServer(int port) {
this.port = port;
}
void start() {
listenThread = new Thread() {
#Override
public void run() {
try (ServerSocket serverSocket = new ServerSocket(port)) {
while (!interrupted()) {
Socket socket = serverSocket.accept();
threadNumber++;
System.out.println(threadNumber+"==========================");
socket.getOutputStream().write(("\"HTTP/1.1 200 OK\\r\\n\"Connection: close\r\n\r\n").getBytes());
// socket.getOutputStream().write("abrakadabra".getBytes());
socket.close();
Thread.sleep(1000);
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
};
listenThread.start();
}
void stop() {
listenThread.interrupt();
}
}
The above code after one client request prints:
Server started!
1==========================
2==========================
When i replace socket.getOutputStream().write(("\"HTTP/1.1 200 OK\\r\\n\"Connection: close\r\n\r\n").getBytes()); with socket.getOutputStream().write("abrakadabra".getBytes());, programm prints:
Server started!
1==========================
2==========================
3==========================
Related
I wrote a simple server client program today, but I have a problem and don't know why.
Here are my 3 important classes(all methods are called properly):
public class Server {
private ServerSocket server;
private ArrayList<Client> clients = new ArrayList<Client>();
public Server(int port) {
try {
server = new ServerSocket(port);
server.setSoTimeout(900000);
} catch (IOException e) {
e.printStackTrace();
}
acceptClients();
Main.frame.log("Server started on port "+port);
}
public void acceptClients() {
Thread t = new Thread() {
#Override
public void run() {
System.out.println("Accepting");
while(true) {
try {
Socket client = server.accept();
System.out.println("Accepted: "+client.getLocalSocketAddress());
clients.add(new Client(client));
} catch (IOException e) {
e.printStackTrace();
break;
}
}
};
};
t.start();
}
}
public class Client {
private static Socket client;
private static DataOutputStream out;
private static DataInputStream in;
public static void main(String[] args) throws UnknownHostException, IOException {
client = new Socket("localhost", 1567);
client.setSoTimeout(900000);
in = new DataInputStream(client.getInputStream());
out = new DataOutputStream(client.getOutputStream());
receive();
send("Hi I am a client!");
}
public static void receive() {
Thread t = new Thread() {
#Override
public void run() {
while (true) {
try {
String data = in.readUTF();
System.out.println("Received: "+data);
send("Test");
} catch (IOException e) {
e.printStackTrace();
break;
}
}
};
};
t.start();
}
public static void send(String data) {
try {
System.out.println("Sending");
out.writeUTF(data);
System.out.println("Sent: "+data);
} catch (IOException e) {
e.printStackTrace();
}
}
}
The client handler of my server:
public class Client {
Socket socket;
DataOutputStream out;
DataInputStream in;
public Client(Socket client) {
socket = client;
try {
socket.setSoTimeout(900000);
in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
receive();
} catch (IOException e) {
e.printStackTrace();
}
}
private void receive() {
Thread t = new Thread() {
#Override
public void run() {
while (true) {
try {
process(in.readUTF());
in.close();
sleep(100);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
break;
}
}
}
};
t.start();
}
public void send(String data) {
try {
out.writeUTF(data);
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private void process(String data) {
Main.frame.log("Received--> "+data);
send("I received your message!");
}
}
When I execute the server and the client everything is fine until the client sends the second message. Then I get this error from the server:
java.net.SocketException: socket closed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at java.io.DataInputStream.readUnsignedShort(Unknown Source)
at java.io.DataInputStream.readUTF(Unknown Source)
at java.io.DataInputStream.readUTF(Unknown Source)
at de.julian.factoryserver.net.Client$1.run(Client.java:33)
And this error from my client:
java.io.EOFException
at java.io.DataInputStream.readUnsignedShort(Unknown Source)
at java.io.DataInputStream.readUTF(Unknown Source)
at java.io.DataInputStream.readUTF(Unknown Source)
at ftc.Client$1.run(Client.java:28)
I hope someone can help me!
In class Server, in method send you seem to have closed the outputstream, dont close it, just flush it
public void send(String data) {
try {
out.writeUTF(data);
out.close(); // remove this and replace it with out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
also in recieve you seem to prematurely close the inputstream
private void receive() {
Thread t = new Thread() {
#Override
public void run() {
while (true) {
try {
process(in.readUTF());
in.close(); // remove this
sleep(100);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
break;
}
}
}
};
t.start();
}
Apply the above fixes and that should fix your exceptions.
I've been trying to make the code below to have multiple clients communicate with the same server.
Currently, it works one client at a time with the server but it seems to be that when the second client opens, code stops at new ObjectInputStream(connection.getInputStream()); in the Class 3 (client) - see below.
I've tried making the inputstream object transient to be shared in different threads but it didn't work, nor with making runClient method synchronized.
If I were to implement Serializable in the client class using serialVersionUID, how can I make multithreading work with the same server or is there any better way..?
Class 1 - server main
public class EchoServer {
private ServerSocket server;
private int portNum;
public static final int DEFAULT_PORT = 8081;
public EchoServer(int portNum) {
this.portNum = portNum;
}
public void runServer() {
System.out.println("Echo Server started...");
try {
server = new ServerSocket(portNum);
Socket connection = server.accept();
new Thread(new ClientHandler(connection)).run();
} catch(IOException ex) {
System.err.println("Error encountered! Port is likely already in use! Exiting program...");
ex.printStackTrace();
}
}
public static void main(String[] args) {
if (args.length > 0) {
(new EchoServer(Integer.parseInt(args[0]))).runServer();
} else {
(new EchoServer(DEFAULT_PORT)).runServer();
}
}
}
Class 2
public class ClientHandler implements Runnable {
private ObjectOutputStream output;
private ObjectInputStream input;
private String message;
/** Integer to hold the message number. */
private int messagenum;
private Socket connection;
public ClientHandler(Socket connection) {
this.connection = connection;
}
#Override
public void run() {
do{
handleRequest();
} while (true);
}
public void handleRequest() {
try {
output = new ObjectOutputStream(this.connection.getOutputStream());
input = new ObjectInputStream(this.connection.getInputStream());
do {
try {
message = (String) input.readObject();
System.out.println(messagenum +" Output> " +message);
} catch (EOFException | SocketException e) {
message = null;
}
if (message != null) {
output.writeObject(messagenum +" FromServer> " +message);
output.flush();
++messagenum;
}
} while (message != null);
input.close();
output.close();
this.connection.close();
} catch (IOException | ClassNotFoundException ex) {
System.err.println("Error encountered! Exiting program...");
ex.printStackTrace();
}
}
}
Class 3 - client main
public class EchoClient implements Serializable {
private static final long serialVersionUID = 1L;
private Socket connection;
private ObjectOutputStream output;
private transient ObjectInputStream input;
private String message = "";
private static String serverName;
public static final String DEFAULT_SERVER_NAME = "localhost";
private static int portNum;
BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in));
public EchoClient(String serverName, int portNum) {
this.serverName = serverName;
this.portNum = portNum;
}
public synchronized void runClient() {
try {
connection = new Socket(InetAddress.getByName(serverName), portNum);
output = new ObjectOutputStream(connection.getOutputStream());
input = new ObjectInputStream(connection.getInputStream());
do {
System.out.print("Input> ");
message = keyboard.readLine();
if (message != null){
output.writeObject(message);
output.flush();
message = (String) input.readObject();
System.out.println(message);
}
} while (message != null);
input.close();
output.close();
connection.close();
} catch (IOException ioException) {
ioException.printStackTrace();
} catch (ClassNotFoundException exception) {
exception.printStackTrace();
}
}
public static void main(String[] args) {
switch (args.length) {
case 2:
(new EchoClient(args[0], Integer.parseInt(args[1]))).runClient();
break;
case 1:
(new EchoClient(DEFAULT_SERVER_NAME, Integer.parseInt(args[0]))).runClient();
break;
default:
(new EchoClient(DEFAULT_SERVER_NAME, server.EchoServer.DEFAULT_PORT)).runClient();
}
}
}
Call server.accept() in the loop to accept multiple client connections as mentioned in the other answers. Start a new thread with the Thread.start method instead of Thread.run- What's the difference between Thread start() and Runnable run().
volatile boolean isRunning = true;
public void runServer() {
System.out.println("Echo Server started...");
try {
server = new ServerSocket(portNum);
while(isRunning) {
Socket connection = server.accept();
new Thread(new ClientHandler(connection)).start();
}
} catch(IOException ex) {
System.err.println("Error encountered! Port is likely already in use! Exiting program...");
ex.printStackTrace();
}
}
run server needs to wait for connections in a loop otherwise it will connect once and that is it. It needs to close its connections too. Clean up its threads. that's just in server main. I'm pretty sure this is a duplicate. So keep on researching
As said by efekctive, you need your server.accept() in a loop, else it will accept the first client and exit the program. So put these two lines in runServer() in a loop like this:
boolean isRunning = true;
while(isRunning){
Socket connection = server.accept();
new Thread(new ClientHandler(connection)).run();
}
Scenario:
a) Persistent connections
b) Manage each server-client communication individually
c) Protect System from propagating exceptions/errors
I tried to created two instances of server socket listeners using the following code :
SimpleSocketServers.java
public class SimpleSocketServers {
public static void main(String[] args) throws Exception {
int port1 = 9876;
SimpleSocketServer server1 = new SimpleSocketServer(port1);
server1.startAndRunServer();
System.out.println("Servers : server1 Listening on port: " + port1);
int port2 = 9875;
SimpleSocketServer server2 = new SimpleSocketServer(port2);
server2.startAndRunServer();
System.out.println("Servers : server2 Listening on port: " + port2);
}
}
and
SimpleSocketServer.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class SimpleSocketServer {
private ServerSocket serverSocket;
private int port;
public SimpleSocketServer(int port) {
this.port = port;
}
public void startAndRunServer() {
try {
System.out.println("Starting Server at port " + port + " ...");
serverSocket = new ServerSocket(port);
System.out.println("Listening for client connection ...");
Socket socket = serverSocket.accept();
RequestHandler requestHandler = new RequestHandler(socket);
requestHandler.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
class RequestHandler extends Thread {
private Socket socket;
RequestHandler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try {
System.out.println("Client Request Response being processed...");
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
}
But, it creates only one instance as control is not returning from the constructor of first instance. Is there any possibility to get back control and run both instances of server socket listeners simultaneously? (ps: Pardon me, if it is wrong or trivial!)
Use 2 Different Threads, Listening To 2 Different Ports.
Thread ServerThread1 = new Thread(new Runnable() {
#Override
public void run() {
ServerSocket ServerSocketObject = null;
while(true)
{
try {
ServerSocketObject = new ServerSocket(Your_Port_Number1);
Socket SocketObject = ServerSocketObject.accept();
// Your Code Here
SocketObject.close();
} catch (IOException e) {
try {
ServerSocketObject.close();
} catch (IOException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
}
}
});
Thread ServerThread2 = new Thread(new Runnable() {
#Override
public void run() {
ServerSocket ServerSocketObject = null;
while(true)
{
try {
ServerSocketObject = new ServerSocket(Your_Port_Number2);
Socket SocketObject = ServerSocketObject.accept();
// Your Code Here
SocketObject.close();
} catch (IOException e) {
try {
ServerSocketObject.close();
} catch (IOException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
}
}
});
ServerThread1.start();
ServerThread2.start();
You need to have SimpleSocketServer implement Runnable; start a thread with itself as the Runnable in the constructor; and run an accept() loop in the run() method. At present you're blocking in the constructor waiting for a connection, and your servers will also only handle a single connection.
The more interesting question is why you want to provide the same service on two ports.
i am making a java socket chat program and i made it compatible for multiple connections and when a user joins it doesn't send the message "[user] Joined" to all clients just to the one that connected but i have a thread for each client if anyone can tell me why it is only sending the message to the user that recently joined i would greatly appreciate it. Here is the server code
import java.io.*;
import java.net.*;
import java.util.ArrayList;
public class server {
public ObjectInputStream input;
public ServerSocket server;
public Socket s;
public ObjectOutputStream output;
public ArrayList<Socket> users = new ArrayList<Socket>();
public class Accept implements Runnable {
public void run() {
try {
server = new ServerSocket(55555, 100);
} catch (IOException e) {
e.printStackTrace();
}
while(true) {
try {
s = server.accept();
users.add(s);
new EchoThread(s).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public class EchoThread extends Thread {
private Socket sock;
public EchoThread(Socket s) throws IOException {
this.sock = s;
output = new ObjectOutputStream(sock.getOutputStream());
}
public void run() {
System.out.println(sock.getInetAddress() + " Connected");
try {
for(Socket s: users) {
output.writeObject(s.getInetAddress() + " Connected");
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
server() throws IOException {
Thread t = new Thread(new Accept());
t.start();
}
public static void main(String[] args) throws IOException {
new server();
}
}
So,
Every time someone connects to the server, u create a new EchoThread.
Each User has his own EchoThread.
Your Server role is to manage all the EchoThreads and Sockets.
output.writeObject(s.getInetAddress() + " Connected");
This only sends a message to ONE user.
Your Server should have a List of Sockets and send messages to every Sockets
public ArrayList<Socket> users = new ArrayList<Socket>();
public ArrayList<ObjectOutputStream> outputs = new ArrayList<ObjectOutputStream>();
public class Accept implements Runnable {
public void run() {
try {
server = new ServerSocket(55555, 100);
} catch (IOException e) {
e.printStackTrace();
}
while(true) {
try {
s = server.accept();
users.add(s);
outputs.add(new ObjectOutputStream(s.getOutputStream()));
for (ObjectOutputStream o: outputs) {
o.writeObject(s.getInetAddress() + " has connected");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
I'm trying to make a simple ECHO server that can manage more client.
Server Class:
public class EchoServer {
protected int port ;
protected ServerSocket socket;
private Socket acceptedSocket;
public EchoServer(int port) throws IOException {
this.port = port;
socket = new ServerSocket(port);
}
public void start() throws AcceptingClientException {
while(!socket.isClosed()) {
try {
acceptedSocket = socket.accept();
}
catch (IOException e){
throw new AcceptingClientException();
}
ClientHandler ch = new ClientHandler(acceptedSocket);
ch.run();
}
}
}
Runnable client handler:
public class ClientHandler implements Runnable {
Socket socket;
public ClientHandler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
PrintWriter From_Server = null;
BufferedReader To_Server = null;
String to_server_string = null;
try {
From_Server = new PrintWriter(socket.getOutputStream());
To_Server =
new BufferedReader(
new InputStreamReader( socket.getInputStream()));
System.out.println("Stream opened.\n");
while(true) {
if(To_Server.ready()){
System.out.println("Reading input line.\n");
to_server_string = To_Server.readLine();
if(to_server_string.equalsIgnoreCase("quit")) {
System.out.println("Connection closed on user request.\n");
From_Server.print("Bye :)\n");
From_Server.close();
To_Server.close();
socket.close();
}
else {
System.out.println(
"String '" +
to_server_string+"' is not 'quit', echoing.\n");
From_Server.print("ECHO: "+to_server_string+"\n");
System.out.println("String written on stream, flushing.\n");
From_Server.flush();
}
}
}
}
catch (IOException e) {
System.out.println("Stream error (connection closed?).\n");
}
}
}
Main Class
public static void main(String[] args) {
try {
EchoServer server= new EchoServer(9999);
server.start();
}
catch (IOException ex) {
System.out.println("Unable to start server (port is busy?)\n");
Logger.getLogger(SimpleServer.class.getName()).log(Level.SEVERE, null, ex);
}
catch (AcceptingClientException e){
System.out.println("Unable to accept client\n");
}
}
More than one client is able to connect to the server, but the ECHO will works only with one client at the time (if I close the connection with one client the server will start to handle another one automatically), but I can't understand why: when a client connects to the server, the associated socked created with server.accept() is passed to a new instance of a runnable client handler which is started with handler.run() and the server should go back on waiting in server.accept() (unless the ServerSocket is closed).
I'm assuming the issue should be with this method of the server class:
public void start() throws AcceptingClientException {
while(!socket.isClosed()) {
try {
acceptedSocket=socket.accept();
}
catch (IOException e){
throw new AcceptingClientException();
}
ClientHandler ch = new ClientHandler(acceptedSocket);
ch.run();
}
}
But I can't figure out what is wrong with it...what am I missing?
Your code:
ClientHandler ch = new ClientHandler(acceptedSocket);
ch.run();
doesn't start a new thread, it delegates to ClientHandler.run() in the same thread.
To start a thread, use new Thread( ch ).start(); since ch is of class ClientHandler which implements Runnable.