I created a simple Client-Server Application, which is working fine.
The server is listening to a port and then starts a thread for the job.
At the moment the only way (outside the IDE) is, to kill the java.exe to stop the server.
Both example classes are very stripped-down.
Main Class:
public static void main(String[] args) {
MultiThreadedServer server = new MultiThreadedServer(9000);
new Thread(server).start();
}
MultiThreadedServer Class:
public class MultiThreadedServer implements Runnable {
protected int serverPort = 9000;
protected ServerSocket serverSocket = null;
protected Thread runningThread = null;
protected ExecutorService threadPool = Executors.newFixedThreadPool(Options.getInstance().getThreadCount());
public MultiThreadedServer(int port) {
this.serverPort = port;
}
public void run() {
synchronized (this) {
this.runningThread = Thread.currentThread();
}
openServerSocket();
while (true) {
Socket clientSocket;
try {
clientSocket = this.serverSocket.accept();
} catch (IOException e) {
throw new RuntimeException("Error accepting client connection", e);
}
try {
this.threadPool.execute(new WorkerRunnable(clientSocket, Constants.appName + " Thread"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void openServerSocket() {
try {
this.serverSocket = new ServerSocket(this.serverPort);
} catch (IOException e) {
throw new RuntimeException("Cannot open port " + serverPort, e);
}
}
}
I am wondering, what is the best practice to start the server application?
I have solved it on my own.
I´ve created a windows batch script, which processes some pre-requirements and starts the server application.
And with nssm nssm I have installed this batch file as windows service. Not the server application is controllable by windows services.
Related
I've created a java server app which opens connections with serverSocket on port 3000 and it works perfectly with java client app I created. But now I started developing client app in react native and I can't understand it's socket API, because socket.io in react native forces me to use WebSocket way.
Is there any other way?
public static final int PORT = 3000;
private ServerSocket mServerSocket = null;
#Override
public void run() {
try {
mServerSocket = new ServerSocket(PORT);
} catch (IOException e) {
close();
return;
}
while (isOpen()) {
try {
mSocket = mServerSocket.accept();
ClientThread clientThread = new ClientThread(new Client(mSocket, this));
mClients.add(clientThread);
clientThread.start();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
try {
mServerSocket.close();
mSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
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 have been working with TCP server/client stuff for a while. I am actully good at UDP programming when it comes to connecting more than one user that is multiple clients. I tried to do the same on a TCP server that i made using Threads but whenever the Thread gets to this piece of code
String reader = (String)in.readObject();
an error is generated and the thread stops executing the code but the thread still runs the program keeping it alive.
Anyway here is the entire source code :
public class TestServer implements Runnable {
private Thread run, streams, connect, receive, send;
private ServerSocket socket;
private Socket conn;
private ObjectInputStream in;
private ObjectOutputStream out;
private boolean running, incomingMessage = false;
private int port;
public TestServer(int port) throws IOException {
this.port = port;
socket = new ServerSocket(port);
console("Server stated on : " + InetAddress.getLocalHost() + " : " + port);
run = new Thread(this, "Run");
run.start();
}
public void run() {
running = true;
connect();
receive();
}
private void connect() {
connect = new Thread("Connect") {
public void run() {
while(running) {
try {
conn = socket.accept();
} catch (IOException e) {
e.printStackTrace();
}
console("You are now connected" + conn.getInetAddress().toString() + " : " + conn.getPort());
try {
setupStreams();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}; connect.start();
}
private void setupStreams() throws IOException {
streams = new Thread("Streams") {
public void run() {
try {
console("Setting up Streams");
out = new ObjectOutputStream(conn.getOutputStream());
out.flush();
in = new ObjectInputStream(conn.getInputStream());
console("Streams are now setup");
incomingMessage = true;
receive.start();
} catch(IOException e) {
e.printStackTrace();
}
}
}; streams.start();
}
private void receive() {
receive = new Thread("Receive") {
public void run() {
while(incomingMessage) {
String message = "";
try {
message = (String) in.readObject();
//This is the only flaw the program
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
console("Client : " + message);
}
}
};
}
private void console(String message) {
System.out.println(message);
}
public static void main(String[] args) {
try {
new TestServer(1234);
} catch (IOException e) {
e.printStackTrace();
}
}
}
FYI am not new to this. The error is caused because the server starts receiving packets even when there are no packets to be received. But because the thread forces it to receive it, i generates the error in the thread and dont know any other way to counter this. So please help. Thanks in Advance.
You shouldn't need 2 threads per connection. One thread is all that's required. After the connection is accepted, pass it to a worker thread to start reading. This can be done in a while loop in the worker thread.
Even though the socket's input stream can be read, the ObjectInputStream() class is more sensitive. If there is any error, its state is corrupted and it can't be used.
while (true) {
try {
Object input = in.readObject();
message = (String) input;
} catch (IOException e) {
e.printStackTrace();
break; //unrecoverable
} catch (ClassNotFoundException e) {
e.printStackTrace();
break; //unrecoverable
}
console("Client : " + message);
}
It's a better design to use a specific message protocol instead of sending serialized Java objects. For example if you are sending Strings like your sample, an InputStreamReader can be used to convert bytes to characters more easily and with less error handling.
These resources would be helpful to you:
https://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html#later
Java - Listening to a socket with ObjectInputStream
ObjectInputStream(socket.getInputStream()); does not work
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.
I'm trying to implement OSGI bundle with network server which uses network sockets.
This is the complete source code: http://www.2shared.com/file/RMXby331/CB_27.html
This is the Activator:
package org.DX_57.osgi.CB_27.impl;
import java.util.Properties;
import org.DX_57.osgi.CB_27.api.CBridge;
import org.DX_57.osgi.CB_27.impl.EchoServer;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
public class CBridgeApp implements BundleActivator {
public void start(BundleContext bc) throws Exception {
ServiceRegistration registerService = bc.registerService(CBridge.class.getName(), new CBridgeImpl(), new Properties());
EchoServer();
}
public void stop(BundleContext bc) throws Exception {
boolean ungetService = bc.ungetService(bc.getServiceReference(CBridge.class.getName()));
}
private void EchoServer() {
EchoServer method = new EchoServer();
}
}
This is the source code if the Java Network server:
package org.DX_57.osgi.CB_27.impl;
import java.net.*;
import java.io.*;
public class EchoServer
{
ServerSocket m_ServerSocket;
public EchoServer()
{
try
{
// Create the server socket.
m_ServerSocket = new ServerSocket(12111);
}
catch(IOException ioe)
{
System.out.println("Could not create server socket at 12111. Quitting.");
System.exit(-1);
}
System.out.println("Listening for clients on 12111...");
// Successfully created Server Socket. Now wait for connections.
int id = 0;
while(true)
{
try
{
// Accept incoming connections.
Socket clientSocket = m_ServerSocket.accept();
// accept() will block until a client connects to the server.
// If execution reaches this point, then it means that a client
// socket has been accepted.
// For each client, we will start a service thread to
// service the client requests. This is to demonstrate a
// multithreaded server, although not required for such a
// trivial application. Starting a thread also lets our
// EchoServer accept multiple connections simultaneously.
// Start a service thread
ClientServiceThread cliThread = new ClientServiceThread(clientSocket, id++);
cliThread.start();
}
catch(IOException ioe)
{
System.out.println("Exception encountered on accept. Ignoring. Stack Trace :");
ioe.printStackTrace();
}
}
}
public static void main (String[] args)
{
new EchoServer();
}
class ClientServiceThread extends Thread
{
Socket m_clientSocket;
int m_clientID = -1;
boolean m_bRunThread = true;
ClientServiceThread(Socket s, int clientID)
{
m_clientSocket = s;
m_clientID = clientID;
}
public void run()
{
// Obtain the input stream and the output stream for the socket
// A good practice is to encapsulate them with a BufferedReader
// and a PrintWriter as shown below.
BufferedReader in = null;
PrintWriter out = null;
// Print out details of this connection
System.out.println("Accepted Client : ID - " + m_clientID + " : Address - " +
m_clientSocket.getInetAddress().getHostName());
try
{
in = new BufferedReader(new InputStreamReader(m_clientSocket.getInputStream()));
out = new PrintWriter(new OutputStreamWriter(m_clientSocket.getOutputStream()));
// At this point, we can read for input and reply with appropriate output.
// Run in a loop until m_bRunThread is set to false
while(m_bRunThread)
{
// read incoming stream
String clientCommand = in.readLine();
System.out.println("Client Says :" + clientCommand);
if(clientCommand.equalsIgnoreCase("quit"))
{
// Special command. Quit this thread
m_bRunThread = false;
System.out.print("Stopping client thread for client : " + m_clientID);
}
else
{
// Echo it back to the client.
out.println(clientCommand);
out.flush();
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
// Clean up
try
{
in.close();
out.close();
m_clientSocket.close();
System.out.println("...Stopped");
}
catch(IOException ioe)
{
ioe.printStackTrace();
}
}
}
}
}
When I try to deploy the bundle on Glassfish server the application server hangs but I can connect to the java network server using the java client. It seems that there is a infinite loop. I need help to fix the code.
Best wishes
Your bundle activator start method never returns, because you're calling constructor of your service with infinite loop. A good practice is to return as fast as possible from bundle activators.
Here is an idea how to rewrite your code:
public class EchoServer {
private volatile boolean started;
public void start() {
new Thread(new Runnable() {
#Override
public void run() {
started = true;
try {
m_ServerSocket = new ServerSocket(12111);
} catch(IOException ioe) {
System.out.println("Could not create server socket at 12111. Quitting.");
System.exit(-1);
}
System.out.println("Listening for clients on 12111...");
// Successfully created Server Socket. Now wait for connections.
int id = 0;
while (started) {
try {
Socket clientSocket = m_ServerSocket.accept();
ClientServiceThread cliThread = new ClientServiceThread(clientSocket, id++);
cliThread.start();
} catch(IOException ioe) {
System.out.println("Exception encountered on accept. Ignoring. Stack Trace :");
ioe.printStackTrace();
}
}
}
}).start();
}
public void stop() {
started = false;
}
}
Activator
public class CBridgeApp implements BundleActivator {
private EchoServer method;
public void start(BundleContext bc) throws Exception {
...
method = new EchoServer();
method.start();
}
public void stop(BundleContext bc) throws Exception {
...
method.stop();
}
}