I'm trying to get a threaded chatserver working. But my socket is closing and I have no clue why it is.
In the server class I create a new ClientHandler
addHandler(new ClientHandler(this, incoming));
addHandler starts the thread and adds the new ClientHandler to an ArrayList in server.
incoming is the client socket.
public ClientHandler(Server serverArg, Socket sockArg) {
server = serverArg;
client = sockArg;
System.out.println(client.isClosed());
}
There is nothing called between
public void run() {
try {
System.out.println(client.isClosed());
in = new Scanner(client.getInputStream());
out = new PrintWriter(client.getOutputStream(), true);
announce();
System.out.println("Waiting for input");
boolean done = false;
while(!done && in.hasNextLine()) {
System.out.println("There is input!");
server.broadcast(clientName + ": " + in.nextLine());
}
} catch (Exception e) {
System.out.println(e.toString());
}
}
When I run this code. This is the output:
false
true
java.net.SocketException: Socket is closed
Why is it closing immediately after creating this class / before starting it?
The connection is being closed by your code between when you add the handler and when the run() method is called. I suggest you add a breakpoint to the close method in the JDK and see where it is called. Or have a look at the code after you add the handler.
You can use a networking sniffer like wireshark or tcpdump.
To find out that if the connection broke due to the server side.
I guess that maybe the client side close the connection.
Related
I have to implement (in the server side) the quit command which disconnects any clients still connected and closes the server.
Here the server code.
public class Server {
public static void main (String args []) {
if (args.length < 1) {
System.err.println("Usage: java Server <port>");
return;
}
int port = Integer.parseInt(args[0]);
try {
ServerSocket listener = new ServerSocket(port);
Files input = new Files();
while (true) {
System.out.println("Listening...");
Socket s = listener.accept();
System.out.println("Connected");
Thread clientHandlerThread = new Thread(new ClientHandler(s,input));
clientHandlerThread.start();
}
} catch (IOException e) {
System.err.println("Error during I/O operation:");
e.printStackTrace();
}
}
}
how can the server accept command line instructions while it is running?
First of all, you have to keep track of all the clients that you create by putting their instances in a list so that when you're going to shutdown everything, you could access them and tell them to finish their job.
And about how to tell the thread instances to do that, you should call their interrup() method to inform them that they should finish/stop whatever it's doing. Calling the interrupt() method on a thread leads an InterruptedException in the thread that you should handle and gracefully finish whatever you're doing.
For example if you have something like this in the run method of your ClientHandler:
while (true) {
try {
Thread.sleep(interval);
} catch (InterruptedException e){
Thread.currentThread().interrupt();
System.out.println(
"We've been asked to finish up the communication. Bye! ;)");
}
// do your business
}
This was of course a very simplified scenario to demonstrate the overall approach. You should be able to find tons of tutorials online about how to use the interrupt.
So, I have the following code that catches a new connection, then hands that connection to its own thread to handle the client.
private void loop(int port) {
// Opens a port for connections.
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(port);
System.out.println("Server running in port " + port);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// Listens for a connection
while (onlineState == true && serverSocket != null) {
Socket clientSocket = new Socket();
try {
clientSocket = serverSocket.accept();
System.out.println(clientSocket.getInetAddress() + " has connected to the port " + clientSocket.getPort());
new Thread(new SocketThread(clientSocket)).run();
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
So, my problem here is that when I try to connect with multiple client apps to the server, the server only seems to either accept one connection at any given time. The client itself is a very simple application of the basic tutorial: it simply repeats any string that the server sends to it.
I have two guesses as to why this is happening: a) there's something wrong with my handling code, b) it's because both connections are from the same IP.
However, neither case is a good thing. Any ideas what I'm doing wrong? (Except everything)
Two things:
You want to call start(), not run() on your Thread object. The difference is that start() actually goes and does threaded stuff, like running it in the background. Calling run() from where you call it there will handle all the client communication right there, inline. That's why you only ever accept one connection - you won't accept any more until you've serviced that client.
You don't want to call clientSocket.close() in your main thread. In your implementation of SocketThread, call clientSocket.close() at the end of your run() method, probably inside a finally block.
Also, does SocketThread extend Thread? If so, you don't need new Thread(), just do
new SocketThread(clientSocket).start();
If it doesn't extend Thread, why not name it SocketRunnable or ClientRunnable or something like that.
I'm building something here and I found myself in a pickle. Just some introduction first. I'm developing a client-server game. One of the functions it has is a chat that players can use to talk to another.
Player1 send a message to the server and the server forwards it to the respective Player2. My problemas is: how can I access classes from another thread so I can get the Socket object to relay the message to Player2.
while (listening)
{
try
{
//this is how I start a thread for each connection
//do I need to use identifiers or something?
new Client(serverSocket.accept()).start();
}
catch(IOException A)
{
reportError(A.toString()); //reportError is a function of mine
}
}
there are many ways to achieve this, the easiest would be:
public void start(){
try {
ServerSocket ss = new ServerSocket(port);
System.out.println("Starting server on port: " + port);
while (serverState) {
Socket socket = ss.accept();
//stop server
if (!serverState) {
break;
}
Client handler = new Client(this, socket);
handler.start();
}
//when server is stopped, close all connections
for (Client client : clients.values()) {
client.closeConnection();
}
} catch (IOException e) {
}
}
if you send "this" inside the constructor of client and set it as a private variable you could Access it from the run function(other thread)
I'm creating a Java based server.
I'm using a server socket to accept incoming messages.
However at some point within my program I want the server socket to listen to another port.
I close the server socket. And start a new one with my new port. Everything is fine.
However when I change the server socket to the previous port again, it gives me an error.
I've read things that the server socket stays a while in a timed-out state after I closed it.
So here is my question:
Can I circumvent this timed-out state of the server socket and make my port available again after I closed it and want to listen to the same port again?
EDIT: my function to make and listen to a server socket & my function to invalidate a server socket and create a new one right after
public void makeServerSocketWithPort(int portnr) throws IOException, Exception
{
server = new ServerSocket(portnr);
server.setReuseAddress(true);
while(!portchanged)
{
Socket sock = server.accept();
System.out.println(server.getLocalPort());
System.out.println(sock.getLocalPort());
handler = new Requesthandler(sock); //should be in a thread
System.out.println(server.getLocalPort());
System.out.println(sock.getLocalPort());
}
}
public void invalidateRequestHandler(int newPort)
{
if(server != null)
{
portchanged = true;
try {
server.close();
} catch (IOException ex) {
Logger.getLogger(Controlserver.class.getName()).log(Level.SEVERE, null, ex);
}
}
portchanged = false;
makeServerSocketWithPort(newPort);
}
Error StackTrace:
Exception in thread "main" java.net.SocketException: Socket closed
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:408)
at java.net.ServerSocket.implAccept(ServerSocket.java:462)
at java.net.ServerSocket.accept(ServerSocket.java:430)
at stuff.Controlserver.makeServerSocketWithPort(Controlserver.java:63)
at stuff.Main.main(Main.java:44)
EDIT:
a second try to fix it to no avail:
public void makeServerSocketWithPort(int portnr, boolean invalidated) throws IOException, Exception
{
if(!invalidated)
{
server = new ServerSocket();
server.setReuseAddress(true);
server.bind(new InetSocketAddress(portnr));
portchanged = false;
}
else
{
//TODO: invalidate the old requestHandler
if(server != null)
{
try
{
server.close();
server = null;
}
catch (IOException ex)
{
Logger.getLogger(Controlserver.class.getName()).log(Level.SEVERE, null, ex);
}
}
if(server.isClosed())
{
System.out.println("closed biatch!");
}
else
{
System.out.println("surprise moddafakkaaaaa!!!");
}
//---------------------------------------------
//then make new requestHandler with new port
portchanged = true;
}
while(!portchanged)
{
if(server != null && !server.isClosed() && !invalidated)
{
Socket sock = server.accept();
System.out.println(server.getLocalPort());
System.out.println(sock.getLocalPort());
System.out.println("test");
handler = new Requesthandler(sock); //should be in a thread
handler.start();
System.out.println("ja harm");
System.out.println(server.getLocalPort());
System.out.println(sock.getLocalPort());
}
else
{
portchanged = true;
}
}
if(portchanged)
{
portchanged = false;
makeServerSocketWithPort(portnr, false);
}
}
Again this works fine normally. I can navigate through my html pages. When I change my port number via one of the webpages it is properly stored and changed in my storage xml files.
But when I changed my socket and navigate immediately to a page through that socket, it says it is closed and is not working until i restart my application.
I'm still looking for a way to circumvent this restart.
Well I solved the mystery.
Thing was I just needed to reconstruct my classes a bit to support the threading a bit better. Instead of closing the socket and then making a new thread I started a new thread and then closed the socket. After a bit of fiddling it appeared to work just fine.
This is the normal Server socket behavior by OS. The OS keeps the port open in WAIT_TIMEOUT state. To get around this, try using ServerSocket.setReuseAddress(boolean on). This will enable/disable the SO_REUSEADDR socket option. Check here for Documentation.
Quoting the javadoc of method setReuseAddress
When a TCP connection is closed the connection may remain in a timeout
state for a period of time after the connection is closed (typically
known as the TIME_WAIT state or 2MSL wait state). For applications
using a well known socket address or port it may not be possible to
bind a socket to the required SocketAddress if there is a connection
in the timeout state involving the socket address or port.
Enabling SO_REUSEADDR prior to binding the socket using
bind(SocketAddress) allows the socket to be bound even though a
previous connection is in a timeout state.
Use TCPview to see all the opened ports in your system. You can close those ports which are in use.
I'm trying to make a multithreaded server/client app with java ! this code is for listen() method in a class of a package that named Bsocket (iserver.core.socket) :
try {
serverSocket = new ServerSocket(port);
}catch(IOException e ){
ui.log(e.toString());//*
}
while (true){
try{
clienSocket = serverSocket.accept();
ui.log("Incomming Connection.");//*
new connectionHandler(clienSocket, ui);
}catch(IOException e ){
ui.log(e.toString());
}
}
ui.log("Incomming Connection."); is a method in below of main class of Bgui (iserver.core.ui).Bgui is a jframe that contain a textarea and something else ! the problem is when the accept methods executed , the ui.log did not works ! whats wrong here ?
You will need to launch your server on a seperate thread since .accept is a blocking call. You might want to do something like so:
(new Runnable() {
#Override
public void run()
{
try {
serverSocket = new ServerSocket(port);
}catch(IOException e ){
ui.log(e.toString());//*
}
while (true){
try{
clienSocket = serverSocket.accept();
ui.log("Incomming Connection.");//*
new connectionHandler(clienSocket, ui);
}catch(IOException e ){
ui.log(e.toString());
}
}
}
}).start();
NOTE: This code is not tested, but it should give you an idea of what you need to do.
Socket.accept() blocks until there's an incoming connection to receive (see the documentation). You shouldn't be making any blocking calls from your UI thread - otherwise it will... you know... block!
You need to separate UI threads from your own network service threads. accept() is blocking (obviously) and it freezes your application until you get a new client, and freezes again waiting for more clients.