I have created Java Web application that has a application listener and that listener creates thread on context initialized that creates ServerSocket that accepts new connections in a loop.
The problem is that every time I re deploy app it gives me java.net.BindException: Address already in use (Bind failed). I have closed the ServerSocket and don't know what else to do. Here is my code:
#Override
public void run() {
int port = Integer.parseInt(conf.getConf("port"));
try (ServerSocket serverSocket = new ServerSocket(port)) {
while (work) {
Socket socket = serverSocket.accept();
System.out.println("User connected!");
WorkThread workThread = new WorkThread(conf, socket, bpk);
workThread.start();
}
}
} catch (IOException ex) {
Logger.getLogger(SocketThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
Thank you in advance!
Related
I want to integrate a server with multiple clients for a blackjack game I created, and thus I began practicing with servers in java. I create a thread, that when ran, forces the server to listen for input and produce an output. Then I added a feature to stop the server. However, the server randomly produces the correct output, and sometimes fails to connect. Here is the code for when the user hosts a server:
st = new ServerThread(); //this is a field of type ServerThread
st.start(); //this runs the server concurrently as a new thread
Here is the code for when they close a server:
st.stopThread();
Finally, here is the source for the serverThread:
public class ServerThread extends Thread {
private volatile boolean isRunning = true;
private Socket socket;
private static final int PORTNUM = 1342;
#Override
public void run() {
while (isRunning) { //should run only when the
try {
ServerSocket serverSocket = new ServerSocket(PORTNUM); //uses the same port number, which I made a constant
//Reading the an object of type Information from the client
socket = serverSocket.accept();
ObjectInputStream serverInputStream = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream serverOutputStream = new ObjectOutputStream(socket.getOutputStream());
Information i = (Information) serverInputStream.readObject();
//arbitrarily changes the data stored in the information object to verify connection with server
i.setI(100);
i.setS("new string");
i.setD(4.4);
//sends the modified object back to the client
serverOutputStream.writeObject(i);
serverInputStream.close();
serverOutputStream.close();
socket.close();
} catch (IOException e) {
//System.out.println("IOException");
//e.printStackTrace();
} catch (ClassNotFoundException e) {
//System.out.println("ClassNotFoundException");
//e.printStackTrace();
} finally {
try {
if (socket != null) { //avoid null pointer if no connections have been established
socket.close();
}
} catch (IOException ex) {
//Logger.getLogger(ServerThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
public void stopThread() {
isRunning = false;
}
}
Any suggestions on edits to make my code perform correctly and consistently would be welcome. Thanks.
I would move the socket definition away from being an instance variable i.e,
while (isRunning) {
Socket socket = null;
try {
...
The once the client disconnects and I restart the client, the server gives read line timeout. and when I run the server again, it works fine. So after disconnect one time I get read line timeout exception and next time it works.
import java.io.*;
public class TcpServer {
ServerSocket welcomeSocket;
public TcpServer() throws IOException{
createSocket(port);
}
public TcpServer(int port) throws IOException{
createSocket(port);
}
private void createSocket(int port) throws IOException{
welcomeSocket = new ServerSocket(port);
}
#Override
public void listen() throws IOException{
boolean exitServer = false;
Socket connectionSocket = null;
try {
while (!exitServer ) {
if(...){
exitServer = true;
}
}
}
} catch (IOException e) {
try {
welcomeSocket.accept();
listen();
} catch (IOException e1) {
System.out.println("Cannot open connection!!!");
}
}
}
}
The ServerSocket.accept() method blocks and returns a new client socket connection when someone tries to connect. Put it in a while loop and then spawn a thread for this new socket worker. Something similar to this:
ServerSocket welcomeSocket = new ServerSocket(port);
while (true) {
Socket socket = welcomeSocket.accept();
new Thread(new RunnableSocketWorker(socket));
}
If your client does decide to disconnect, that's fine, let them. You want the socket worker that was working on it to exit. If a new client tries to connect, they will do so above with your ServerSocket object and this infinite loop.
A big reason sockets are relatively easy in Java is that this ServerSocket class handles all incoming new clients. Why would you want to code that part yourself?
Just take the socket it returns and have fun!
I have a TcpServer class that is responsible to, well, act like a tcp server. You can find the class below :
public class TcpServer {
private ServerSocket serverSocket;
private Socket socket;
private int locallyBoundPort;
public TcpServer() {
}
public TcpServer(int locallyBoundPort) {
try {
this.serverSocket = new ServerSocket(locallyBoundPort);
serverSocket.setReuseAddress(true);
} catch (IOException e) {
System.out.println("Error at binding to port TCP : " + locallyBoundPort + "...cause : " + e.getMessage());
}
socket = null;
}
public void accept() {
try {
socket = serverSocket.accept();
socket.setReuseAddress(true);
} catch (IOException e) {
System.out.println("Error at accept : " + locallyBoundPort);
}
}
public void send(Data data) throws IOException {
if(socket != null) {
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
out.writeObject(data);
}
}
public Data receive() throws ClassNotFoundException, IOException {
if(socket != null) {
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
return (Data) in.readObject();
} else {
return null;
}
}
public boolean bind(int port) throws IOException {
try {
this.serverSocket = new ServerSocket(port);
this.locallyBoundPort = port;
} catch(IOException e) {
return false;
}
return true;
}
public void close() {
try {
serverSocket.close();
socket.close();
} catch (IOException e) {
OzumUtils.print("IOException in close, TcpServer");
}
}
public int getLocallyBoundPort() {
return locallyBoundPort;
}
public Socket getSocket() {
return socket;
}
public ServerSocket getServerSocket() {
return serverSocket;
}
}
And I have a code piece that does this :
TcpServer tcpServer = new TcpServer(LocalPort);
while(1)
{
tcpServer.accept();
Thread thread = new Thread(new runnable(tcpServer));
thread.start();
tcpServer = new TcpServer(LocalPort);
}
However I am getting a port already in use error. I thought two different socket instances could listen to the same port as multiplexing allows two connections through the same port when the connector has different ip or port ?
What am I missing?
You cannot bind two tcp server sockets to the same port. reuseAddress is really for client sockets, and it does not work the way you think it does ... and the way you are using it would not do anything at all either way (because you are setting it after binding).
You don't really need to bind twice to the same port either. Just remove this line tcpServer = new TcpServer(LocalPort); from the bottom of your while loop, and you'll be all set.
The way this works is that you bind your server socket once and listen to the port. When a connection arrives, it forks a client socket for you to communicate with the client, and the original server socket continues to listen for more connections.
Basically, you need to remove the socket member (and any other state) from your TcpServer, and make the accept method return the accepted socket. Then make your runnable take that socket as a parameter instead of the TcpServer, and use that to serve the client connection. Then just keep calling accept in the loop, and forking threads for new connections same way you do know, except do not recreate the server every time.
Or, alternatively, remove the server socket and port from TcpServer, create the socket outside the loop, then while(true) call accept on it, create a new TcpServer with the returned client socket, and use it in a thread to process the connection.
Do not forget to close client sockets after you are done with them.
No, you can't use a port already in listening state. However any number of clients can connect to this same port. You don't need to listen to the port again, you just spawn a new thread to process the current connection and wait for a new one. For example, supposing you have a class TcpConnectionHanlder that implements Runnable and takes the Socket as parameter, the loop would look like
while (true) { //while(1) is not valid Java syntax
final Socket tcpSocket = tcpServer.accept(); // Get socket for incoming connection
final Thread thread = new Thread(new TcpConnectionHanlder(tcpSocket)); // Create a thread for this socket/client connection
thread.start(); // Launch the thread
// tcpServer = new TcpServer(LocalPort); <- not needed, port still listening.
}
Then in your TcpConnectionHanlder instance you handle this particular client (socket).
I am making a program that requires the UI to update every time a client receives data from a server. To to this the socket and serversocket have to be closed and reopened every time. Although when the program tries to accept the new connection, here is my code and the error:
public void startServer(){
Thread serverstart = new Thread(){
public void run() {
try {
serversocket = new ServerSocket(socket);
while(true){
skt = serversocket.accept();
close.setEnabled(true);
new Thread(new newClient(skt)).start();
}
} catch (IOException e){
e.printStackTrace();
}
}
};serverstart.start();
}
static class newClient implements Runnable {
private Socket socket;
static PrintStream output;
public newClient(Socket skt){
this.socket = skt;
}
#Override
public void run(){
try {
output = new PrintStream(socket.getOutputStream());
} catch(IOException ioe){
ioe.printStackTrace();
}
}
}
public void sendData(){
tallydata = Integer.toString(preview) + " " + Integer.toString(program);
System.out.println(tallydata);
newClient.output.print(tallydata);
try{
skt.close();
serversocket.close();
} catch(IOException e){
e.printStackTrace();
}
startServer();
}
The socket is closed at the end of the sendData() method and the startServer() method is called to restart the connection again after that. Here is the error:
java.net.SocketException: Socket closed
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:398)
at java.net.ServerSocket.implAccept(ServerSocket.java:522)
at java.net.ServerSocket.accept(ServerSocket.java:490)
at TallySystem.servergui$1.run(servergui.java:201)
Thanks.
Why are you closing and reopening the server anyway? Just start it once and leave it alone. Thats how it should be used.
Anyway, as per the ServerSocket documentation:
public void close()
Closes this socket. Any thread currently blocked in accept() will throw a SocketException.
Thats precisely your problem. You are closing the ServerSocket while its busy awaiting connections.
I am trying to build a java microblogging app
I have finished the code but cannot connect to my own computer due to the following error (I google it and someone said I need to change the port number. I changed the port number and nothing happened)
Exception in thread "Thread-4" java.net.BindException: Address already in use: JVM_Bind
Below is the code for the server:
public class server extends Thread {
public Socket client = null;
public ServerSocket server = null;
private int port = 4444;
public void run(){
while (true){ //loop waits for incomming connection
try { //start the server and listen to a port
server = new ServerSocket(port);
}catch (IOException e){
System.err.println(e);
System.exit(-1);
}
try { //establish a connection when receiving request
client = server.accept();
}catch (IOException e){
System.err.println(e);
System.exit(1);
}
Thread t = new Thread(new Connection(client));
t.start();
}
}
}
And this is the code to start the server and listen to port 4444
Server server = new Server();
server.start(); //to listen to a port
Thank you
You must create the ServerSocket before entering the loop. At present you are trying to create it every iteration, which doesn't make sense, and you aren't closing it, so the second creation fails.