I have a server class which connects a client on a specific server socket port and starts off a thread with a service class. Specifically, I have 3 service classes so I would like to have 3 different ports. This however, is not working as I had expected it to. This is my code for the server:
import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
public class WebsiteServer {
public static void main(String args[]) throws IOException {
ServerSocket serversocket = new ServerSocket(22401);
ServerSocket serversocket2 = new ServerSocket(22402);
Thread thread;
Thread thread2;
Socket socket;
Socket socket2;
NewUserService newuserservice;
ExistingUserService existinguserservice;
System.out.println("Waiting for clients to connect.");
while (true) {
socket = serversocket.accept();
socket2 = serversocket2.accept();
if(socket.isConnected()) {
System.out.println("NewUserClient has connected.");
newuserservice = new NewUserService(socket);
thread = new Thread(newuserservice);
thread.start();
}
if(socket2.isConnected()) {
System.out.println("ExistingUserClient has connected.");
existinguserservice = new ExistingUserService(socket2);
thread2 = new Thread(existinguserservice);
thread2.start();
}
}
}
}
It works fine if I only use one port for example:
import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
public class WebsiteServer {
public static void main(String args[]) throws IOException {
ServerSocket serversocket = new ServerSocket(22401);
ServerSocket serversocket2 = new ServerSocket(22402);
Thread thread;
Thread thread2;
Socket socket;
Socket socket2;
NewUserService newuserservice;
ExistingUserService existinguserservice;
System.out.println("Waiting for clients to connect.");
while (true) {
socket = serversocket.accept();
//socket2 = serversocket2.accept();
if(socket.isConnected()) {
System.out.println("NewUserClient has connected.");
newuserservice = new NewUserService(socket);
thread = new Thread(newuserservice);
thread.start();
}
// if(socket2.isConnected()) {
//
// System.out.println("ExistingUserClient has connected.");
// existinguserservice = new ExistingUserService(socket2);
// thread2 = new Thread(existinguserservice);
// thread2.start();
// }
}
}
}
Any help would be appreciated.
The accept method blocks until a connection is made. So, you are sitting blocked one one .accept(), even though the other server may have activity. One simple solution would be to make one listening thread per server.
accept()is a blocking method. In other words, the second accept() is waiting for another connection. Untik a second connection is accepted, your code will be blocked
You need to call the accept() method in a separate thread. accept() blocks the thread until someone joins the server. This could be 1 ms or 1 year.
I suggest you create an AcceptListener to be called when someone joins
public interface AcceptListener{
public void socketAccepted(Socket s);
}
And a handler class
public class MyServerSocket extends Thread{
private AcceptListener l;
private boolean run = true;
private ServerSocket s;
public MyServerSocket(AcceptListener l, int port){
this.l = l;
this.s = new ServerSocket(port);
this.start();
}
public void run(){
while(run){
l.socketAccepted(s.accept());
}
}
}
You'll have to handle errors and whatnot and make the overrides in you subclass(es) of AcceptListener.
Related
Disclaimer: I'm fairly new to Java, so mabye it's a stupid question.
Here we go.
I am writing a program that listens on a port, accepts a connection, does its thing, and closes the port.
I want this to run in it's own thread which handles the complete communication. So, ServerSocket.accept() would be started in the thread.
But how can I only spawn a thread if I need it? I can not know if I receive data if I didn't use ServerSocket.accept() yet, but if I do this in the main method, I will not be able to accept a new one while this one is open.
Some sample code omitting imports for clarity:
public class communicator implements Runnable{
private ServerSocket server;
private Socket socket;
Thread t;
communicator(ServerSocket server){
this.server = server;
t = new Thread(this,"MyThread");
t.start();
}
public void run() {
try {
socket = server.accept();
//do stuff
socket.close();
} catch (IOException ex) {
Logger.getLogger(communicator.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
and the main class:
public class test {
private static ServerSocket server;
private static Socket socket;
public static void main(String[] args) throws IOException{
server = new ServerSocket(123);
communicator comm = new communicator(server);
}
}
Or maybe I can use something like, "if one thread is active, provide a new one"?
Thx.
You can use Threadpools and an ExecturonerService something like this.
public class Listener implements Runnable {
private ServerSocket serverSocket;
ExecutorService executorService = Executors.newCachedThreadPool();
public Listener(ServerSocket serverSocket) {
this.serverSocket = serverSocket;
}
#Override
public void run() {
try {
while (true) {
Socket accept = serverSocket.accept();
executorService.execute(new Worker(accept));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Listener waits until a connection comes, creates a new Worker object and gives it the executioner service to run it. This service will handle the number of threads that are needed for you und clean everything up when the task is done.
public class Worker implements Runnable{
private Socket socket;
public Worker(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
//do stuff
}
}
Scenario: A program starts a server and listens for another program to connect to said server; if another program connects, kill the server on the old program and start the same server on the new program, and repeat the cycle.
After running the program for the first time, I get:
thread started
attempting connection
server started
Then, after running the program again, the first instance reads:
thread started
attempting connection
server started
Another instance was started, this instance has been shut down
Exception in thread "Thread-0" java.lang.NullPointerException
at me.aj.phoenix.util.JustOneServer.startServer(JustOneServer.java:37)
at me.aj.phoenix.util.JustOneServer.run(JustOneServer.java:28)
and the second instance reads:
attempting connection
Another instance was running and has been closed.
server started
java.net.BindException: Address already in use: NET_Bind
at java.base/java.net.PlainSocketImpl.bind0(Native Method)
at java.base/java.net.PlainSocketImpl.socketBind(PlainSocketImpl.java:132)
at java.base/java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:436)
at java.base/java.net.ServerSocket.bind(ServerSocket.java:381)
at java.base/java.net.ServerSocket.<init>(ServerSocket.java:243)
at java.base/java.net.ServerSocket.<init>(ServerSocket.java:187)
at me.aj.phoenix.util.JustOneServer.startServer(JustOneServer.java:34)
at me.aj.phoenix.util.JustOneServer.run(JustOneServer.java:26)
Essentially what im trying to do is whenever a new version of the program is started, close the older program and start the listener on the newer program
Here is the code:
public class TestProgram extends Thread {
public final int port = 9665;
ServerSocket serverSocket = null;
Socket clientSocket = null;
#Override
public void run() {
System.out.println("thread started");
try {
this.check();
this.startServer();
} catch (IOException ioe) {
this.startServer();
}
}
public void startServer() {
try {
System.out.println("server started");
serverSocket = new ServerSocket(port, 1);
clientSocket = serverSocket.accept();
Logger.print("Another instance was started, this instance has been shut down");
System.exit(0);
} catch (IOException e) {
e.printStackTrace();
}
}
public void check() throws UnknownHostException, IOException {
System.out.println("attempting connection");
Socket socket = new Socket("localhost", port);
if(socket.isConnected()) {
Logger.print("Another instance was running and has been closed.");
}
}
}
The second program is not waiting for the first programs listening server to unbind from the port, and I'm not quite sure how to fix it.
The main problem is that the logic in startServer method should run in an infinite loop to account for the weak nature of sockets that may be disconnected at any time, and more importantly for the scenario in which is trying to connect to a port that is bound by a previous instance that is in the process of shutting down.
while (true)
runServer(port);
Other problems include closing resources when problems arise and nesting away the exceptions that arise from a client Socket from those that come from a ServerSocket; so that whenever an exception is thrown for a ServerSocket is not interpreted as an exception that would end the execution of startServer method.
void runServer(int port) {
try (ServerSocket serverSocket = new ServerSocket(port, 1)) {
logger.debug("Server started!");
try (Socket clientSocket = serverSocket.accept()) {
logger.debug("Signal to shutdown received. Shutting down.");
System.exit(0);
}
} catch (IOException e) {
logger.debug("The other application is still shutting down...");
}
}
The following is a complete working example of this:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ServerReplacer {
private static Logger logger = LoggerFactory.getLogger(ServerReplacer.class);
public static void runReplacerService(int port) {
searchOlderInstances(port);
logger.debug("Server starting...");
while (true)
runServer(port);
}
private static void searchOlderInstances(int port) {
logger.debug("Attempting to find older instance...");
try (Socket socket = new Socket("127.0.0.1", port)) {
logOtherInstanceFound(socket.isConnected());
} catch (Exception e) {
logOtherInstanceFound(false);
}
}
private static void logOtherInstanceFound(boolean otherInstanceFound) {
logger.debug(otherInstanceFound ?
"FOUND ANOTHER INSTANCE RUNNING! It has been signaled to shut down." :
"No older instance found.");
}
private static void runServer(int port) {
try (ServerSocket serverSocket = new ServerSocket(port, 1)) {
logger.debug("Server started!");
try (Socket clientSocket = serverSocket.accept()) {
logger.debug("Signal to shutdown received. Shutting down.");
System.exit(0);
}
} catch (IOException e) {
logger.debug("The other application is still shutting down...");
}
}
public static void main(String[] args) {
runReplacerService(9665);
}
}
Complete code on GitHub
Hope this helps.
I'm new in Networking and I'm trying to make a small java application for chatting.
What I want is the ServerSocket to accept one and only one connection.If a second Socket tries to connect to the ServerSocket it will throw an exception so the user who launched the socket knows that he can't connect to that ServerSocket
I looked at the javadoc and I've found that constructor.
public ServerSocket(int port, int backlog) throws IOException
Creates a server socket and binds it to the specified local port number, with the specified backlog. A port number of 0 means that the port number is automatically allocated, typically from an ephemeral port range. This port number can then be retrieved by calling getLocalPort.
and I tried this
class Service implements Runnable {
private Socket maChaussette;
Service(Socket s) {
maChaussette = s;
}
public void run() {
System.out.println("connection established");
while (true) {
System.out.print("");
}
//maChaussette.close();
}
}
Server :
class Serv {
public static void main(String[] a) throws IOException {
ServerSocket socketAttente;
socketAttente = new ServerSocket(11111, 1);
boolean conn = false;
Thread t;
while (true) {
Socket s = socketAttente.accept();
t = new Thread(new Service(s));
t.start();
}
//socketAttente.close();
}
}
client
public class Cll {
public static final int PORT = 11111;
public static void main(String[] arguments) {
try {
Socket service = new Socket("localhost", PORT);
while (true) {
System.out.print("");
}
} catch (Exception e) {
System.err.println("Error");
e.printStackTrace();
System.exit(1);
}
}
}
I don't try to communicate or something, I just made these classes to try to block the number of connections to the ServerSocket.
But with that code if I run two Cll program I got two times the message "connection established ".
does Anybody have an idea about how to proceed to limit connections on a ServerSocket ?
Just close the ServerSocket after you accept one connection. And get rid of the 'while (true)' around the accept loop.
I am working on a java program that is essentially a chat room. This is an assignment for class so no code please, I am just having some issues determining the most feasible way to handle what I need to do. I have a server program already setup for a single client using threads to get the data input stream and a thread to handle sending on the data output stream. What I need to do now is create a new thread for each incoming request.
My thought is to create a linked list to contain either the client sockets, or possibly the thread. Where I am stumbling is figuring out how to handle sending the messages out to all the clients. If I have a thread for each incoming message how can I then turn around and send that out to each client socket.
I'm thinking that if I had a linkedlist of the clientsockets I could then traverse the list and send it out to each one, but then I would have to create a dataoutputstream each time. Could I create a linkedlist of dataoutputstreams? Sorry if it sounds like I'm rambling but I don't want to just start coding this, it could get messy without a good plan. Thanks!
EDIT
I decided to post the code I have so far. I haven't had a chance to test it yet so any comments would be great. Thanks!
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.ServerSocket;
import java.util.LinkedList;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class prog4_server {
// A Queue of Strings used to hold out bound Messages
// It blocks till on is available
static BlockingQueue<String> outboundMessages = new LinkedBlockingQueue<String>();
// A linked list of data output streams
// to all the clients
static LinkedList<DataOutputStream> outputstreams;
// public variables to track the number of clients
// and the state of the server
static Boolean serverstate = true;
static int clients = 0;
public static void main(String[] args) throws IOException{
//create a server socket and a clientSocket
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(6789);
} catch (IOException e) {
System.out.println("Could not listen on port: 6789");
System.exit(-1);
}// try{...}catch(IOException e){...}
Socket clientSocket;
// start the output thread which waits for elements
// in the message queue
OutputThread out = new OutputThread();
out.start();
while(serverstate){
try {
// wait and accept a new client
// pass the socket to a new Input Thread
clientSocket = serverSocket.accept();
DataOutputStream ServerOut = new DataOutputStream(clientSocket.getOutputStream());
InputThread in = new InputThread(clientSocket, clients);
in.start();
outputstreams.add(ServerOut);
} catch (IOException e) {
System.out.println("Accept failed: 6789");
System.exit(-1);
}// try{...}catch{..}
// increment the number of clients and report
clients = clients++;
System.out.println("Client #" + clients + "Accepted");
}//while(serverstate){...
}//public static void main
public static class OutputThread extends Thread {
//OutputThread Class Constructor
OutputThread() {
}//OutputThread(...){...
public void run() {
//string variable to contain the message
String msg = null;
while(!this.interrupted()) {
try {
msg = outboundMessages.take();
for(int i=0;i<outputstreams.size();i++){
outputstreams.get(i).writeBytes(msg + '\n');
}// for(...){...
} catch (IOException e) {
System.out.println(e);
} catch (InterruptedException e){
System.out.println(e);
}//try{...}catch{...}
}//while(...){
}//public void run(){...
}// public OutputThread(){...
public static class InputThread extends Thread {
Boolean threadstate = true;
BufferedReader ServerIn;
String user;
int threadID;
//SocketThread Class Constructor
InputThread(Socket clientSocket, int ID) {
threadID = ID;
try{
ServerIn = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
user = ServerIn.readLine();
}
catch(IOException e){
System.out.println(e);
}
}// InputThread(...){...
public void run() {
String msg = null;
while (threadstate) {
try {
msg = ServerIn.readLine();
if(msg.equals("EXITEXIT")){
// if the client is exiting close the thread
// close the output stream with the same ID
// and decrement the number of clients
threadstate = false;
outputstreams.get(threadID).close();
outputstreams.remove(threadID);
clients = clients--;
if(clients == 0){
// if the number of clients has dropped to zero
// close the server
serverstate = false;
ServerIn.close();
}// if(clients == 0){...
}else{
// add a message to the message queue
outboundMessages.add(user + ": " + msg);
}//if..else...
} catch (IOException e) {
System.out.println(e);
}// try { ... } catch { ...}
}// while
}// public void run() { ...
}
public static class ServerThread extends Thread {
//public variable declaration
BufferedReader UserIn =
new BufferedReader(new InputStreamReader(System.in));
//OutputThread Class Constructor
ServerThread() {
}//OutputThread(...){...
public void run() {
//string variable to contain the message
String msg = null;
try {
//while loop will continue until
//exit command is received
//then send the exit command to all clients
msg = UserIn.readLine();
while (!msg.equals("EXITEXIT")) {
System.out.println("Enter Message: ");
msg = UserIn.readLine();
}//while(...){
outboundMessages.add(msg);
serverstate = false;
UserIn.close();
} catch (IOException e) {
System.out.println(e);
}//try{...}catch{...}
}//public void run(){...
}// public serverThread(){...
}// public class prog4_server
I have solved this problem in the past by defining a "MessageHandler" class per client connection, responsible for inbound / outbound message traffic. Internally the handler uses a BlockingQueue implementation onto which outbound messages are placed (by internal worker threads). The I/O sender thread continually attempts to read from the queue (blocking if required) and sends each message retrieved to the client.
Here's some skeleton example code (untested):
/**
* Our Message definition. A message is capable of writing itself to
* a DataOutputStream.
*/
public interface Message {
void writeTo(DataOutputStream daos) throws IOException;
}
/**
* Handler definition. The handler contains two threads: One for sending
* and one for receiving messages. It is initialised with an open socket.
*/
public class MessageHandler {
private final DataOutputStream daos;
private final DataInputStream dais;
private final Thread sender;
private final Thread receiver;
private final BlockingQueue<Message> outboundMessages = new LinkedBlockingQueue<Message>();
public MessageHandler(Socket skt) throws IOException {
this.daos = new DataOutputStream(skt.getOutputStream());
this.dais = new DataInputStream(skt.getInputStream());
// Create sender and receiver threads responsible for performing the I/O.
this.sender = new Thread(new Runnable() {
public void run() {
while (!Thread.interrupted()) {
Message msg = outboundMessages.take(); // Will block until a message is available.
try {
msg.writeTo(daos);
} catch(IOException ex) {
// TODO: Handle exception
}
}
}
}, String.format("SenderThread-%s", skt.getRemoteSocketAddress()));
this.receiver = new Thread(new Runnable() {
public void run() {
// TODO: Read from DataInputStream and create inbound message.
}
}, String.format("ReceiverThread-%s", skt.getRemoteSocketAddress()));
sender.start();
receiver.start();
}
/**
* Submits a message to the outbound queue, ready for sending.
*/
public void sendOutboundMessage(Message msg) {
outboundMessages.add(msg);
}
public void destroy() {
// TODO: Interrupt and join with threads. Close streams and socket.
}
}
Note that Nikolai is correct in that blocking I/O using 1 (or 2) threads per connection is not a scalable solution and typically applications might be written using Java NIO to get round this. However, in reality unless you're writing an enterprise server which thousands of clients connect to simultaneously then this isn't really an issue. Writing bug-free scalable applications using Java NIO is difficult and certainly not something I'd recommend.
i have coded a socket listener that should listen on port 80 and 81 and when data arrive on these ports execute operations on these data. I want this listener to concurrently listen on both these ports and hav coded in the following way.
import java.net.*;
import java.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
public class MultipleSocketServer implements Runnable {
private int a;
private ServerSocket connection;
private String TimeStamp;
private int ID;
public static void main(String[] args){
// System.out.print("ip");
// String gh="12345";
//System.out.println(gh.substring(1,3));
int port = 80;
int port1 = 81;
int count = 0;
double a=234.52121;
//System.out.println(bf3.toString());
try{
ServerSocket socket1 = new ServerSocket(port);
ServerSocket socket2=new ServerSocket(port1);
System.out.println("MultipleSocketServer Initialized");
Runnable runnable = new MultipleSocketServer(socket1, ++count);
Runnable run = new MultipleSocketServer(socket2, ++count);
Thread thread = new Thread(runnable);
Thread thread1 = new Thread(run);
while (true) {
//Socket connection = socket1.accept();
thread.start();
thread1.start();
}
}
catch (Exception e) {}
}
MultipleSocketServer(ServerSocket s, int i) {
this.connection = s;
this.ID = i;
}
public void run() {
while(true){
try {
Socket incoming=connection.accept();
BufferedInputStream is = new BufferedInputStream(incoming.getInputStream());
int character;
while((character = is.read())!=-1) {
.
.
do the input data handling here
.
.
}
}
catch(Exception e){}
}
}
}
But for some reason this does not seem to show the threaded/conncurrent behaviour.
I am testing this code using Hyperterminal, and every time i disconnect from hyperterminal, the program execution stops and "Socket is closed" exception is raised.
Any pointers would be of great help
Cheers
You're starting threads in an endless loop.
while (true) {
//Socket connection = socket1.accept();
thread.start();
thread1.start();
}
I think though, that this is handled (ignored) in
} catch (Exception e) {}
However, I suspect that the problem you describe is in in the handling code you didn't include. One pretty obvious idea: you don't call connection.close() instead of incoming.close(), do you?