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.
Related
I am trying to create a multi-threaded duplex chat server. I had it working fine before I moved the code into threads, but now I'm getting "SocketException: Socket is closed" whenever a thread tries to access a socket.
My teacher and I can't figure it out. (teacher knows even less Java than I do; he is a C guy). It seems like the socket is open, but as soon as it goes into the thread, it is closed.
What am I doing wrong?
Client code:
public class Client {
public static void main(String[] args) throws IOException {
String hostName = "localhost";
int portNumber = 6969;
try (
Socket socket = new Socket(hostName, portNumber);
) {
System.out.println("Chat connected");
//Sender
if (!socket.isClosed())
new Thread(new Sender(socket)).start();
//Receiver
if (!socket.isClosed())
new Thread(new Receiver(socket)).start();
} catch (SocketException e) {
System.out.println("Connection terminated unexpectedly");
}
}
}
Server code:
public class Server {
public static void main(String[] args) throws IOException {
int portNumber = 6969;
try (
ServerSocket serverSocket = new ServerSocket(portNumber);
Socket clientSocket = serverSocket.accept();
) {
//Receiver
if (!clientSocket.isClosed())
new Thread(new Receiver(clientSocket)).start();
//Sender
if (!clientSocket.isClosed())
new Thread(new Sender(clientSocket)).start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Receiver thread code:
class Receiver implements Runnable {
private Socket socket;
Receiver(Socket s) throws IOException {
socket = s;
}
#Override
public void run() {
try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
String received;
do {
received = in.readLine();
if (received == null) break;
System.out.println("Them: " + received);
} while (!received.contains("/dropmic"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
Sender thread code:
class Sender implements Runnable {
private Socket socket;
Sender(Socket s) throws IOException {
socket = s;
}
#Override
public void run() {
try (PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) {
String sent;
do {
System.out.print("You: ");
sent = stdIn.readLine();
if (sent == null) break;
out.println(sent);
} while (!sent.contains("/dropmic"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
Server output:
java.net.SocketException: Socket is closed
at java.net.Socket.getOutputStream(Socket.java:943)
at Sender.run(Sender.java:16)
at java.lang.Thread.run(Thread.java:745)
java.net.SocketException: Socket closed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:170)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:161)
at java.io.BufferedReader.readLine(BufferedReader.java:324)
at java.io.BufferedReader.readLine(BufferedReader.java:389)
at Receiver.run(Receiver.java:19)
at java.lang.Thread.run(Thread.java:745)
Process finished with exit code 0
Client output (Still running):
Chat connected
You: java.net.SocketException: Socket is closed
at java.net.Socket.getInputStream(Socket.java:903)
at Receiver.run(Receiver.java:16)
at java.lang.Thread.run(Thread.java:745)
You are using a try-with-resources statement, and putting the socket as the resources. However, when you create the new thread, this try-with-resources reaches the end of its code and closes the sockets. Put your sockets inside the actual try statement and close them manually to fix this.
This socket application works perfectly fine until I add support for multiple client connections to the server. Then I get a EOFException from the client, and a SocketException: Socket closed from the server.
Server.java:
public class Server {
static final int PORT = 8005;
static final int QUEUE = 50;
public Server() {
while (true) {
try (ServerSocket serverSocket = new ServerSocket(PORT, QUEUE);
Socket socket = serverSocket.accept();
DataInputStream input = new DataInputStream(socket.getInputStream());
DataOutputStream output = new DataOutputStream(socket.getOutputStream())) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
output.writeUTF("Hey, this is the server!");
output.flush();
System.out.println(input.readUTF());
} catch (IOException e) {
System.out.println();
e.printStackTrace();
}
}
});
thread.start();
} catch (IOException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new Server();
}
}
Client.java:
public class Client {
static final String HOST = "localhost";
static final int PORT = 8005;
public Client() {
try (Socket socket = new Socket(HOST, PORT);
DataInputStream input = new DataInputStream(socket.getInputStream());
DataOutputStream output = new DataOutputStream(socket.getOutputStream())
) {
System.out.println(input.readUTF());
output.writeUTF("Hey, this is the client!");
output.flush();
} catch (IOException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
public static void main(String[] args) {
new Client();
}
}
A couple problems here:
You're creating a new ServerSocket for each pass through the loop. For a multi-client server you should instead be opening one ServerSocket and calling accept() on it for each client that connects.
Try-with-resources closes all resources it's provided with as soon as the try block is exited. You're creating a Thread that uses output but executes independently of the try block, so the execution flow is leaving the try block before thread finishes executing, resulting in socket (and output) being closed before the thread is able to use them. This is one of those situations where your resources need to be used outside the scope of the try block (in the thread you create to use them), so try-with-resources can't do all your resource handling for you.
I would rearrange your server code to something like:
public class Server {
static final int PORT = 8005;
static final int QUEUE = 50;
public Server() {
// create serverSocket once for all connections
try (ServerSocket serverSocket = new ServerSocket(PORT, QUEUE)) {
while (true) {
// accept a client connection, not in a try-with-resources so this will have to be explicitly closed
final Socket socket = serverSocket.accept();
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
// limit scope of input/output to where they're actually used
try (DataInputStream input = new DataInputStream(socket.getInputStream());
DataOutputStream output = new DataOutputStream(socket.getOutputStream())) {
output.writeUTF("Hey, this is the server!");
output.flush();
System.out.println(input.readUTF());
} catch (IOException e) {
System.out.println();
e.printStackTrace();
}
// implicitly close socket when done with it
try {
socket.close();
} catch (IOException e) {
System.out.println();
e.printStackTrace();
}
}
});
thread.start();
}
} catch (IOException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
public static void main(String[] args) {
new Server();
}
}
Code is commented somewhat to explain some of the moves. Also note that the socket.close() call is in its own try-catch block to ensure that it's called even if the I/O streams throw an exception. It could equivalently (or perhaps more correctly now that I think about it) been placed in a finally block on the I/O stream try-catch block.
So now, I am making a client server app based multithread. In server side, I make a thread for everysingle connection that accepted.
In thread class, I make a method that send a command to client. What i just want is, how to send a parameter to all running client? For simple statement, i just want to make this server send a message to all connected client.
I've been read this post and find sendToAll(String message) method from this link. But when i am try in my code, there is no method like that in ServerSocket .
Okay this is my sample code for server and the thread.
class ServerOne{
ServerSocket server = null;
...
ServerOne(int port){
System.out.println("Starting server on port "+port);
try{
server = new ServerSocket(port);
System.out.println("Server started successfully and now waiting for client");
} catch (IOException e) {
System.out.println("Could not listen on port "+port);
System.exit(-1);
}
}
public void listenSocket(){
while(true){
ClientWorker w;
try{
w = new ClientWorker(server.accept());
Thread t = new Thread(w);
t.start();
} catch (IOException e) {
System.out.println("Accept failed: 4444");
System.exit(-1);
}
}
}
protected void finalize(){
try{
server.close();
} catch (IOException e) {
System.out.println("Could not close socket");
System.exit(-1);
}
}
}
class ClientWorker implements Runnable{
Socket client;
ClientWorker(Socket client){
this.client = client;
}
public void run(){
...
sendCommand(parameter);
...
}
public void sendCommand(String command){
PrintWriter out = null;
try {
out = new PrintWriter(client.getOutputStream(), true);
out.println(command);
} catch (IOException ex) {}
}
}
Thanks for help :)
The below answer, is not recommended for a full fledged server, as for this you should use Java EE with servlets, web services etc.
This is only intended where a few computers want to connect to perform a specific task, and using simple Java sockets is not a general problem. Think of distributed computing or multi-player gaming.
EDIT: I've - since first post - greatly updated this architecture, now tested and thread-safe. Anybody who needs it may download it here.
Simply use (directly, or by subclassing) Server and Client, start() them, and everything is ready. Read the inline comments for more powerful options.
While communication between clients are fairly complicated, I'll try to simplify it, the most possible.
Here are the points, in the server:
Keeping a list of connected clients.
Defining a thread, for server input.
Defining a queue of the received messages.
A thread polling from the queue, and work with it.
Some utility methods for sending messages.
And for the client:
Defining a thread, for client input.
Defining a queue of the received messages.
A thread polling from the queue, and work with it.
Here's the Server class:
public class Server {
private ArrayList<ConnectionToClient> clientList;
private LinkedBlockingQueue<Object> messages;
private ServerSocket serverSocket;
public Server(int port) {
clientList = new ArrayList<ConnectionToClient>();
messages = new LinkedBlockingQueue<Object>();
serverSocket = new ServerSocket(port);
Thread accept = new Thread() {
public void run(){
while(true){
try{
Socket s = serverSocket.accept();
clientList.add(new ConnectionToClient(s));
}
catch(IOException e){ e.printStackTrace(); }
}
}
};
accept.setDaemon(true);
accept.start();
Thread messageHandling = new Thread() {
public void run(){
while(true){
try{
Object message = messages.take();
// Do some handling here...
System.out.println("Message Received: " + message);
}
catch(InterruptedException e){ }
}
}
};
messageHandling.setDaemon(true);
messageHandling.start();
}
private class ConnectionToClient {
ObjectInputStream in;
ObjectOutputStream out;
Socket socket;
ConnectionToClient(Socket socket) throws IOException {
this.socket = socket;
in = new ObjectInputStream(socket.getInputStream());
out = new ObjectOutputStream(socket.getOutputStream());
Thread read = new Thread(){
public void run(){
while(true){
try{
Object obj = in.readObject();
messages.put(obj);
}
catch(IOException e){ e.printStackTrace(); }
}
}
};
read.setDaemon(true); // terminate when main ends
read.start();
}
public void write(Object obj) {
try{
out.writeObject(obj);
}
catch(IOException e){ e.printStackTrace(); }
}
}
public void sendToOne(int index, Object message)throws IndexOutOfBoundsException {
clientList.get(index).write(message);
}
public void sendToAll(Object message){
for(ConnectionToClient client : clientList)
client.write(message);
}
}
And here for the Client class:
public class Client {
private ConnectionToServer server;
private LinkedBlockingQueue<Object> messages;
private Socket socket;
public Client(String IPAddress, int port) throws IOException{
socket = new Socket(IPAddress, port);
messages = new LinkedBlokingQueue<Object>();
server = new ConnecionToServer(socket);
Thread messageHandling = new Thread() {
public void run(){
while(true){
try{
Object message = messages.take();
// Do some handling here...
System.out.println("Message Received: " + message);
}
catch(InterruptedException e){ }
}
}
};
messageHandling.setDaemon(true);
messageHandling.start();
}
private class ConnectionToServer {
ObjectInputStream in;
ObjectOutputStream out;
Socket socket;
ConnectionToServer(Socket socket) throws IOException {
this.socket = socket;
in = new ObjectInputStream(socket.getInputStream());
out = new ObjectOutputStream(socket.getOutputStream());
Thread read = new Thread(){
public void run(){
while(true){
try{
Object obj = in.readObject();
messages.put(obj);
}
catch(IOException e){ e.printStackTrace(); }
}
}
};
read.setDaemon(true);
read.start();
}
private void write(Object obj) {
try{
out.writeObject(obj);
}
catch(IOException e){ e.printStackTrace(); }
}
}
public void send(Object obj) {
server.write(obj);
}
}
There is no method in server socket to send data or message to all running clinet threads.
Please go through the ServerThread.java program which is calling the sendToAll usng server.
// ... and have the server send it to all clients
server.sendToAll( message );
Check out zeroMQ. There are methods known as "pub sub" or "publish subscribe" that will do what you want. You can also use it to communicate between your threads. It is an amazing library in my opinion. It has java or jzmq bindings along with over 30+ others as well so you should be able to use it in your program.
http://www.zeromq.org/
i try creating client-server app using socket.
i already succeed doing that with the AVD and run both server and client on my pc machine.
but when i try make it work in same Wifi network on my device, the app just crash.
yes, i'm using seperate thread for the connection
and already added the use of Internet to the manifest.
here is some code...
the client thread:
package com.mainlauncher;
import java.io.*;
import java.net.*;
public class ConnectionThread extends Thread {
private static final int SERVERPORT = 7777;
private static final String SERVERADDRESS = "My-PC";
private Socket socket;
private DataInputStream in;
private DataOutputStream out;
#Override
public void run() {
super.run();
open();
close();
}
void open(){
try{
socket = new Socket(SERVERADDRESS,SERVERPORT);
in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
}
catch(IOException e){}
}
void close(){
try {
if(in!=null)
in.close();
if(out!=null)
out.close();
if(socket!=null)
socket.close();
}
catch (IOException e) {}
socket=null;
}
}
the Server side main:
import java.io.IOException;
import java.net.*;
public class Main {
public static void main(String[] args) {
int port = 7777;
new Main().handleClients(port);
}
private void handleClients(int port) {
ServerSocket serverSocket = null;
try{
serverSocket = new ServerSocket(port);
System.out.println("Server is ready...");
for(int i=1; ; i++){
Socket socket = serverSocket.accept();
ServerThread thread = new ServerThread(i,socket);
System.out.println(i + " Connected");
thread.run();
}
}
catch (Exception e){
System.err.println(e.getMessage());
}
finally{
if(serverSocket != null){
try{ serverSocket.close(); }
catch(IOException x){}
}
}
}
}
and the ServerThread:
import java.io.*;
import java.net.*;
public class ServerThread extends Thread {
private int serverIndex;
private Socket socket;
private DataOutputStream out;
private DataInputStream in;
public ServerThread (int serverIndex, Socket socket){
this.serverIndex = serverIndex;
this.socket = socket;
}
#Override
public void run() {
super.run();
try {
in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
System.out.println(serverIndex + " Disconnected");
}
finally{
try {
in.close();
out.close();
socket.close();
} catch (IOException e) {}
}
}
}
i tried looking for answers here \ google etc...
nothing helped.
there is no firewall or anything to block the incoming connection on my pc.
any ideas anyone?
thanks,
Lioz
This won't immediately solve your problem, but you have a couple of bugs that are causing your program to throw away the evidence of the the real problem.
1) This simply squashed the exception, throwing away all evidence that it ever happened.
catch(IOException e){}
2) This is a bit better, but it only prints out the exception message ... not the stack trace.
catch (Exception e){
System.err.println(e.getMessage());
}
The other problem with 2) is that it catches ALL exceptions ... not just IOExceptions. That includes unchecked exceptions like NullPointerException, SecurityException and so on.
Exceptions should be diagnosed like this:
catch (IOException e){
e.printStackTrace();
}
or logged.
Finally, the way that you are handling requests is wrong:
Socket socket = serverSocket.accept();
ServerThread thread = new ServerThread(i,socket);
System.out.println(i + " Connected");
thread.run();
The mistake is in the last statement. What this actually does is to simply call the thread object's run() method ... in the current thread. To run the run() method in a different thread you need to call the start method. Like this:
Socket socket = serverSocket.accept();
ServerThread thread = new ServerThread(i,socket);
System.out.println(i + " Connected");
thread.start();
In my code (below) the the serverSocket won't accept a new connection until a thread deals with the existing connection and calls close() on the socket that serverSocket.accept() created. If i start this server and open two tabs in the browser then only one of the tabs connects and the other is left waiting until the other tab finishes (which it doesn't) before serverSocket.accept() will accept a new connection. How can i accept a new connection without closing the previous one?
public class ReboundServer {
static ServerSocket serverSocket;
public static boolean listening = true;
/**
* #param args
* #throws IOException
*/
public static void main(String[] args) throws IOException {
try {
serverSocket = new ServerSocket(4444);
System.out.println("Starting Server");
} catch (IOException e) {
System.out.println("Could not listen on port: 4444");
System.exit(-1);
}
while(listening)
{
(new Thread(new ClientThread(serverSocket.accept()))).start();
}
serverSocket.close();
}
}
public class ClientThread implements Runnable {
private Socket clientSocket = null;
public ClientThread(Socket socket)
{
this.clientSocket = socket;
}
public void run()
{
System.out.println("ClientConnected");
MatchThread.QueueLock.lock();
MatchThread.connectionQueue.add(clientSocket);
MatchThread.QueueLock.unlock();
}
}
Obviously the problem is not here but in the MatchThread class whose code you haven't posted. It appears you have a single thread dealing with that queue. Why?