close all the sockets after using it? on server side - java

Do I have to close all the sockets after using it? Where should I put them in this code? My program just works normally when I run it. However, when I re-run it, it said "Exception in thread "main" java.net.BindException: Address already in use: JVM_Bind". Therefore, I think I did not close all the socket after using it.
import java.io.*;
import java.net.*;
import java.util.*;
public class Server2 {
public static void main(String args[]) throws Exception {
int PORT = 5555; // Open port 5555
//open socket to listen
ServerSocket server = new ServerSocket(PORT);
Socket client = null;
while (true) {
System.out.println("Waiting for client...");
// open client socket to accept connection
client = server.accept();
System.out.println(client.getInetAddress()+" contacted ");
System.out.println("Creating thread to serve request");
ServerStudentThread student = new ServerStudentThread(client);
student.start();
}
}
}

Call server.close() in a finally block.
ServerSocket server = new ServerSocket(PORT);
try {
while (true) {
System.out.println("Waiting for client...");
// open client socket to accept connection
Socket client = server.accept();
System.out.println(client.getInetAddress()+" contacted ");
System.out.println("Creating thread to serve request");
ServerStudentThread student = new ServerStudentThread(client);
student.start();
}
} finally {
server.close();
}

Address already in use: JVM_Bind - means, that you operation system is not closed socket after previous use. It closes on timeout about 30-180 seconds.
I don't realy know how to do this in java, but in C code it may be done like this, before bind system function call:
int yes = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
That mean: set the flag (option) SO_REUSEADDR to sockfd socket.
In java must exists appropriate mechanism for do the same.

You are running an infinite while loop , have a boolean variable to say when to stop , i think you are not exiting gracefully, that is why port is not closed.
May be you can try like this
import java.io.*;
import java.net.*;
import java.util.*;
public class Server2 {
static int NUM_CONN_TO_WAIT_FOR=15;
boolean exitServer =false;
public static void main(String args[]) throws Exception {
int PORT = 5555; // Open port 5555
//open socket to listen
ServerSocket server = new ServerSocket(PORT);
Socket client = null;
static int connections =0;
try
{
while (!exitServer ) {
System.out.println("Waiting for client...");
// open client socket to accept connection
if ( connections < NUM_CONN_TO_WAIT_FOR )
{
client = server.accept();
System.out.println(client.getInetAddress()+" contacted ");
System.out.println("Creating thread to serve request");
ServerStudentThread student = new ServerStudentThread(client);
student.start();
} else
{
exitServer =true;
}
connections++;
}
} catch (Exception e)
{
System.out.println(e.printStackTrace());
}
finally
{
if ( client != null)
client.close();
if ( server!= null)
server.close();
}
}
}

Related

problem with connecting multiple clients to a server

hey I'm writing a simple code with a server socket and multiple clients which the server gets every client's username and stores them in a hashmap.the server accepts a socket client and the client enters the username but again the server accept the same socket client and it wants its username and the code stops here.i want it to work for multiple clients not just one.
server class:
public class Server implements Serializable{
// [..]
public void serverConnect() throws IOException, ClassNotFoundException
{
listener = new ServerSocket(9090);
System.out.println("Server is running...");
while (true)
{
System.out.println("Waiting ...");
socket=listener.accept();
for (Socket socket:socketList.keySet())
{
if (this.socket==socket)
{
checkSocket=false;
}
}
if (checkSocket)
{
socketList.put(socket,socketNumber);
System.out.println("Client is connected");
inputReader = new InputStreamReader(socket.getInputStream());
reader = new BufferedReader(inputReader);
user = reader.readLine();
Server.userList.add(user);
socketNumber++;
}
checkSocket=true;
}
}
}
client class:
public class Client {
public Client() {
}
public void clientConnect() throws UnknownHostException, IOException {
System.out.println("enter your username");
Scanner scanner = new Scanner(System.in);
String msg = scanner.nextLine();
Socket socket = new Socket("localhost", 9090);
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
writer.println(msg);
}
}
In principle you have the workings of single thread server (which means it can accept only one client connection at a time). The main issue is that you have over-complicated how you receive a connection.
You can simplify your current code by dealing by moving the client connection socket and readers into the local scope and dealing with the socket directly.
public void serverConnect() throws IOException {
listener = new ServerSocket(9090);
System.out.println("Server is running...");
while (true) {
System.out.println("Waiting ...");
Socket socket = listener.accept();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
String user = reader.readLine();
Server.userList.add(user);
} catch (IOException ignore) {
} finally {
socket.close();
}
}
}
As you can see you don't need to keep hold of the socket beyond reading the value sent. If you are only expecting the one line of data from the client, you should also close the socket otherwise the client can hold the server hostage by not sending any data until the socket timeout is reached.
Further to this you also want to wrap the code inside the while loop with a try/catch block to prevent an exception terminating the server.
As I mentioned in the opening paragraph this code works as a single threaded server and it can only respond to a single request at a time. If you want to accept and process multiple requests you will need to spawn a new thread to handle the response. I would recommend constructing your code as below but for the sake of brevity you could do something like below:
public void serverConnect() throws IOException {
int MAX_WORKERS = 100;
ExecutorService service = Executors.newFixedThreadPool(MAX_WORKERS);
ServerSocket listener = new ServerSocket(9090);
System.out.println("Server is running...");
while (true) {
System.out.println("Waiting ...");
Socket socket = listener.accept();
service.submit(() -> {
System.out.println("Client is connected");
try {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
String user = reader.readLine();
Server.userList.add(user);
} finally {
socket.close();
}
} catch (Throwable ignore) {
}
});
}
}
So all that is happening above is that we are creating a thread pool of 100 threads using the ExecutorService. This means in theory we can accept 100 concurrent connections.
When a connection is accepted, we submit the socket and worker code to a thread which means that the main thread can return to listening for a new connections.

How can i see if a socket is already connected to my server?

I'm writing a client/server app in java. Is this code correct to check if some socket of a client is already connected to my server? I'm quite new and it is my first app with this characteristics so don't kill me...
package ServerCommunication;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class MultiServer {
public void openSocket() throws IOException {
ServerSocket serverSocket = null;
boolean listening = true;
MultiServerThread w=null;
try {
serverSocket = new ServerSocket(1633);
System.out.println("Waiting on 1633.");
} catch (IOException e) {
System.err.println("Could not listen on port: 1633.");
System.exit(-1);
}
while (listening) {
System.out.println("Hearing");
Socket mysocket=serverSocket.accept();
if(mysocket.isConnected())
System.out.println("Already connected");
else{
System.out.println("Need to create one");
w = new MultiServerThread(mysocket);
Thread t = new Thread(w);
t.start();
}
}
serverSocket.close();
System.out.println("Multiserver closed");
}
}
No.
while (listening) {
System.out.println("Hearing");
Socket mysocket=serverSocket.accept();
The result of executing this line of code is either an IOException or a Socket connected to the client.
if(mysocket.isConnected())
Pointless. It's connected. Remove.
System.out.println("Already connected");
Of course it's connected. That's what accept() is for. Remove.
else{
Unreachable. Remove.
System.out.println("Need to create one");
No you don't. Remove.
w = new MultiServerThread(mysocket);
Thread t = new Thread(w);
t.start();
This is all pointless. Remove.

java.net.BindException: Permission denied when creating a ServerSocket on Mac OSX

I Tried to run a Java socket in mac with eclipse but it doesn't work. I got this error:
Exception in thread "main" java.net.BindException: Permission denied
at java.net.PlainSocketImpl.socketBind(Native Method)
at java.net.PlainSocketImpl.socketBind(PlainSocketImpl.java:521)
at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:414)
at java.net.ServerSocket.bind(ServerSocket.java:326)
at java.net.ServerSocket.<init>(ServerSocket.java:192)
at java.net.ServerSocket.<init>(ServerSocket.java:104)
at server.MessageServer.main(MessageServer.java:11)
How can i make it to run?
package server; //ChatServer
import java.io.*;
import java.net.*;
public class MessageServer {
public static void main (String args[]) throws IOException {
int port = 100;
ServerSocket server = new ServerSocket (port);
System.out.println("Server is started!");
while (true) {
Socket client = server.accept ();
System.out.println ("Accepted from " + client.getInetAddress ());
MessageHandler handler = new MessageHandler (client);
handler.start();
}
}
}
You can't open a port below 1024, if you don't have root privileges and from the code you posted in your comment, you seem to be trying to open port 100 which confirms my theory.
You need to use a port which is higher than 1024, if you're running the code under a non-root user.
Unix-based systems declare ports < 1024 as "privileged" and you need admin rights to start a server.
For testing, use a port number >= 1024.
When deploying the server in production, run it with admin rights.
I had the same issue and my port numbers were below 1024 changing port number to above 1024 solved my problem. Ports below 1024 are called Privileged Ports and in Linux (and most UNIX flavors and UNIX-like systems), they are not allowed to be opened by any non-root user.
Many systems declare ports that are less than 1024 as "admin rights" ports. Meaning, if you're only using this for basic testing use a higher port such as 2000. This will clear the exception that you're getting by running your current program.
int port = 100;
ServerSocket server = new ServerSocket (port);
Change that to something such as:
int port = 2000;
ServerSocket server = new ServerSocket (port);
MyServer.java
import java.io.*;
import java.net.*;
public class MyServer
{
ServerSocket ss;
Socket s;
DataOutputStream dos;
DataInputStream dis;
public MyServer()
{
try
{
System.out.println("Server Started ");
ss=new ServerSocket(4444);
s=ss.accept();
System.out.println(s);
System.out.println("Client Connected");
dis=new DataInputStream(s.getInputStream());
dos=new DataOutputStream(s.getOutputStream());
ServerChat();
}
catch(Exception e)
{
System.out.println(e);
}
}
public static void main(String arg[])
{
new MyServer();
}
public void ServerChat()throws IOException
{
String str;
do
{
str=dis.readUTF();
System.out.println("Client msg : "+str);
dos.writeUTF("Hello "+str);
dos.flush();
}while(!str.equals("stop"));
}
}
MyClient.java
import java.io.*;
import java.net.*;
public class MyClient
{
Socket s;
DataInputStream din;
DataOutputStream dout;
public MyClient()
{
try
{
s=new Socket("localhost",4444);
System.out.println(s);
din = new DataInputStream(s.getInputStream());
dout = new DataOutputStream(s.getOutputStream());
ClientChat();
}
catch(Exception e)
{
System.out.println(e);
}
}
public void ClientChat() throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String s1;
do
{
s1=br.readLine();
dout.writeUTF(s1);
dout.flush();
System.out.println("Server Msg : "+din.readUTF());
}while(!s1.equals("stop"));
}
public static void main(String arg[])
{
new MyClient();
}
}
Run Server program with root (Administrator).
Windows: Run as Administrator the IDE/Editor.
Ubuntu/macOS: sudo java...
This is an old question, and I might be replying too late, but I would like to anyways share my experience in case anyone hits the issue.
I was using port# 8000, but still unable to bind to the port from a java program. It was network filter running as part of eset endpoint security that was blocking the connection.
I added a rule in eset firewall to allow port 8000, and it started working.

How to connect 2 different computers on a network using a chat application in Java?

I have a simple pair of client and server programs. Client connects to server and when it does connect, the server replies with a "Hello there" message. How should I modify the program if I want the client and server programs to run on different systems?
Here is the code for the client side..
package practice;
import java.io.*;
import java.net.*;
public class DailyAdviceClient
{
public static void main(String args[])
{
DailyAdviceClient dac = new DailyAdviceClient();
dac.go();
}
public void go()
{
try
{
Socket incoming = new Socket("127.0.0.1",4242);
InputStreamReader stream = new InputStreamReader(incoming.getInputStream());
BufferedReader reader = new BufferedReader(stream);
String advice = reader.readLine();
reader.close();
System.out.println("Today's advice is "+advice);
}
catch(Exception e)
{
System.out.println("Client Side Error");
}
}
}
and here is the code for the server
package practice;
import java.io.*;
import java.net.*;
public class DailyAdviceServer
{
public static void main(String args[])
{
DailyAdviceServer das = new DailyAdviceServer();
das.go();
}
public void go()
{
try
{
ServerSocket serversock = new ServerSocket(4242);
while(true)
{
Socket outgoing = serversock.accept();
PrintWriter writer = new PrintWriter(outgoing.getOutputStream());
writer.println("Hello there");
writer.close();
}
}
catch(Exception e)
{
System.out.println("Server Side Problem");
}
}
}
just change "127.0.0.1" on the client with the server's IP and make sure the port 4242 is open.
Socket incoming = new Socket("127.0.0.1",4242);
This is creating a socket listening to the server at the address 127.0.0.1 on port 4242. If you change the server to another address, for example of a different pc, then change the ip address that your socket is listening to.
It is also worth noting that you will probably have to open up or allow access to the ports you are using.
Client requires ip address and port of server, means ip of that system which you making server and port (4242).so in client you need to change
Socket incoming = new Socket("127.0.0.1",4242); BY
Socket incoming = new Socket("IP address of server",4242);
And make sure both system is connected via wired or wireless network.

Creating a simple internet chat

I tried to create a simple chat via sockets and it works for LAN right now and for "localhost" too, of course, but not among different computers through the internet and thats the real point of a chat, isn't it!
socket = new Socket("--ip address--", 7345);
This line works for --ip address-- = localhost and --ip address-- = ""my local ip-address"", but with the ip address of my router, it throws a java.net.ConnectException
" java.net.ConnectException: Connection refused: connect "
I want to use my pc as server and not a real server, maybe there is the problem, but I think that there must be a solution. If that is an absurd simple question, don't doom me, because I'm a real newbie in network programming.
When you are creating a server, you have to use server socket with the ip address of where it's running...
The server socket needs to be running on your machine of your machine's ip address.
With your router, you need to forward the connections to the port you are running on your that is hosting the server.
Then you should be able to connect from outside your local network.
Without the code for what your are doing it's hard to tell if that's the only problem here is a simple chat server that might give you guidance.
import java.net.*;
import java.io.*;
public class ChatServer
{ private Socket socket = null;
private ServerSocket server = null;
private DataInputStream streamIn = null;
public ChatServer(int port)
{ try
{
System.out.println("Binding to port " + port + ", please wait ...");
server = new ServerSocket(port);
System.out.println("Server started: " + server);
System.out.println("Waiting for a client ...");
socket = server.accept();
System.out.println("Client accepted: " + socket);
open();
boolean done = false;
while (!done)
{ try
{ String line = streamIn.readUTF();
System.out.println(line);
done = line.equals(".bye");
}
catch(IOException ioe)
{
done = true;
}
}
close();
}
catch(IOException ioe)
{ System.out.println(ioe);
}
}
public void open() throws IOException
{ streamIn = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
}
public void close() throws IOException
{ if (socket != null) socket.close();
if (streamIn != null) streamIn.close();
}
public static void main(String args[])
{ ChatServer server = null;
if (args.length != 1)
System.out.println("Usage: java ChatServer port");
else
server = new ChatServer(Integer.parseInt(args[0]));
}
}

Categories