When a user connects to my server, I'm accepting the connection, storing the connected clients details in an arraylist then im trying to send that list to the client to create an asynchronous list. However, when I try to send the list it breaks the connection and causes the error;
java.net.SocketException: Socket is closed
My server class;
while (true) {
Socket clientSocket = serverSocket.accept();
ServerClientComs clientThread = new ServerClientComs(clientSocket);
getUsername(clientSocket, clientThread);
updateList();
try {
clientThread.sendList(connections);
clientThread.initialiseCommunication();
clientThread.start();
}
catch (IOException error) {
System.out.println("Server: Unable to initialise client thread! - " + error);
}
}
ServerClientComs Class;
public ServerClientComs(Socket clientSocket) {
super();
this.client = client;
this.clientSocket = clientSocket;
}
public void initialiseCommunication() throws IOException {
output = new PrintWriter(this.clientSocket.getOutputStream(), true);
input = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
}
public void sendList(ArrayList connections) throws IOException
{
oos = new ObjectOutputStream(this.clientSocket.getOutputStream());
oos.writeObject(connections);
oos.close();
}
Been playing about with this for a good hour, getting annoying now. any help is greatly appreciated!
A 'Socket closed' exception means that the application that caught the exception closed the socket and then kept trying to use it. Please note that closing the input or output stream of a socket closes the other stream and the socket as well. According to your statements seems you close the stream before using the socket to send data.
Related
If I have a server and a client and I opened a socket between the two:
1.Is it possible that the client will have a printWriter stream, in order to write things to the socket, but the server won't have in the mean time a bufferReader?
If the answer of 1 is yes, if that client will send a message to the server (who currently doesn't have a reading stream), what will happend to this message until te server will create a reading stream and read the message?
thank you
This is not at all specific to Java, but TCP/IP. There are buffers to keep the data received, so it's not possible that some data would be lost because one end isn't "ready" yet. This is because TCP will retransmit data that hasn't been acknowledged as received, guaranteeing that all the bytes that are written are received on the other (barring obvious cases).
in addition to #Kayaman's answer:
consider this Compile-able simple Java implemented example:
Server Side:
import java.io.*;
import java.net.*;
public class SimpleServer implements Runnable{
int serverPort = 45000;
ServerSocket serverSocket = null;
boolean isStopped = false;
public SimpleServer(int port){
this.serverPort = port;
}
public void run(){
try {
serverSocket = new ServerSocket(serverPort);
} catch (IOException e) {
System.err.println("Cannot listen on this port.\n" + e.getMessage());
System.exit(1);
}
while(!isStopped){
try {
Socket clientSocket = serverSocket.accept();
} catch (IOException e) {
// do nothing
}
}
}
public static void main(String[] args) throws IOException {
SimpleServer server = new SimpleServer(45000);
new Thread(server).start();
System.out.println("Server is waiting to connect");
}
}
Client Side:
import java.io.*;
import java.net.*;
public class SimpleClient {
public static void main(String[] args) throws IOException {
Socket socket = null;
PrintWriter out = null;
try {
socket = new Socket("127.0.0.1", 45000);
out = new PrintWriter(socket.getOutputStream(), true);
System.out.println("output stream created");
out.write(9);
System.out.println("message was sent to output with no listener");
} catch (UnknownHostException e) {
// do nothing
} catch (IOException e) {
// do nothing
}
}
}
the example is an implementation of a very basic client server connection in which a socket is created and a stream is defined only on the client side, followed by a write to the stream that will eventually be read by the server (if at all).
therefore, to answer you questions:
1) yes, it's possible to open a one-way connection stream without a "listener"
2) edit: according to #EJP: It will be saved within the socket's buffer until it is read or the socket is closed.
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'm learning about java sockets in a class of mine. I'm having issues with the communication between the peers. My question is why am I receiving this exception:
Exception java.net.ConnectionException: Connection refused: connect
for example:
in my main thread
ServerSocket listenSock = new ServerSocket(Integer.parseInt(argv[2]),0,InetAddress,getByName(null));
//Create Server loop to process inbound connections
while(true){
//accept an incoming client by saving it to a socket to use to communicate with it
Socket clientSock = listenSock.accept();
/waa/create a thread to handle the inbound client so that we can return to accept()
InboundHandler inboundMsg = new InboundHandler(clientSock); // listens to the peers outbound socket
Thread inThread = new Thread(inboundMsg);
inThread.start();
// add the peer to the list.
}
in a seperate thread I have a
public InboundHandler(Socket socket) throws Exception{
this.socket = socket; //save the socket object to "this" instance of the class
input = new BufferedReader(new InputStreamReader(socket.getInputStream())); // listens from the clients speaking socket
}
public void run(){
while(true){
try{
String line = input.readLine();
System.out.println(line);
}catch(IOException e){
System.out.println("Could not read input. " + e);
}
}
and finally I have a thread that sends out messages
for(int i=0;i<portList.size(); i++){
if(nameList.get(i)!=Username){
Socket peerSocket= new Socket(InetAddress.getByName(null),portList.get(i));
writer = new BufferedWriter(new OutputStreamWriter(peerSocket.getOutputStream()));
writer.write(Username + " has connected");
writer.flush();
}
}
}
catch(IOException e){
System.out.println("Some IO problem. " + e);
}
My program compiles, and when I run it, I receive the Exception
java.net.ConnectionException: Connection refused: connect
From what it's sounding like, is the port that my one peer is trying to speak to, isn't being heard by the other peers. But this is more guessing
As for the while(true) I am going to change that later, with a boolean statement.
I am trying to create a multiclient chat sort of server in which we have multiple clients connecting to server and whatever message a client enters, it gets displayed to all the clients(including the client who sent the message). I am not getting this output, instead the message just echoes only on the sender client and no other client. Code is quite long, hence i am displaying snippets of whichever code i think will help you understand error. In case, it is not enough, just comment which part you require. Thanks in advance. I am stuck on this since about hour and half, so i appreciate whatever help i would get.
The Server Class
public class Multiserver {
ServerSocket serversocket;
Socket socket;
ArrayList<Socket> al = new ArrayList<Socket>();
DataInputStream dis;
DataOutputStream dos;
Multiserver() throws IOException
{
serversocket = new ServerSocket(1036);
System.out.println("Server started on port 1036");
while(true)
{
socket = serversocket.accept();
System.out.println(socket);
al.add(socket);
Mythread thread = new Mythread(socket, al);
thread.start();
}
}
Thread used in server class
public class Mythread extends Thread{
Socket socket;
ArrayList al;
DataInputStream dis;
DataOutputStream dos;
Mythread(Socket socket, ArrayList al)
{
this.socket = socket;
this.al = al;}
public void run()
{
try{
String data ="";
dis = new DataInputStream(socket.getInputStream());
data = dis.readUTF();
if(!data.equals("stop"))
{
broadcast(data);
}
else
{
dos = new DataOutputStream(socket.getOutputStream());
// data = dos.readUTF();
dos.writeUTF(data);
dos.flush();
//dos.close();
}
}
catch(Exception e){
System.out.println("Run "+e);
}
}
public void broadcast(String data)
{
try{
Iterator it = al.iterator();
while(it.hasNext())
{
Socket socket1 = (Socket)it.next();
dos = new DataOutputStream(socket1.getOutputStream());
dos.writeUTF(data);
dos.flush();
}
}
catch(Exception e){
System.out.println("Broadcast running "+ e);
}
}
}
The client class
public class Multiclient {
Socket socket;
DataInputStream dis;
DataOutputStream dos;
Multiclient() throws IOException
{
socket = new Socket("127.0.0.1", 1036);
System.out.println(socket);
Mythreadc my = new Mythreadc(socket);
my.start();
}
Thread used in client class
public class Mythreadc extends Thread{
DataInputStream dis;
DataOutputStream dos;
Socket socket;
Mythreadc(Socket socket)throws IOException
{
this.socket = socket;}
public void run()
{
BufferedReader br = null;
try{
br = new BufferedReader(new InputStreamReader (System.in));
dos = new DataOutputStream(socket.getOutputStream());
String data = "";
do{
data = br.readLine();
dos.writeUTF(data);
System.out.println(data);
dos.flush();
}
while(!data.equals("stop"));
}
catch(Exception e)
{
System.out.println("Client input "+e);
}
finally{
try{
br.close();
dis.close();
dos.close();
}
catch(Exception e)
{
System.out.println("Closing "+e);
}
}
}
}
I am sorry i have put on such a long code, almost all the program. But i feel it is necessary to understand where the problem lies.I have tried and i think it lies in the part where we display data written in the client's socket in the client thread class but i don't know what it is ???
#EDIT: Forgot to mention. The client stops when he sends the message "Stop"!
There are two problems with your code that are preventing the clients from displaying more than one message.
Problem one: Your client code never actually displays or prints out the messages it receives from the server. The line
dos = new DataOutputStream(socket.getOutputStream());
creates an OutputStream you can use to write data to the socket, i.e. send messages to the server. But you never use the socket's InputStream, which is what you need to do to read data from the socket, i.e. receive messages from the server. When you see a message printed out on the client, you're actually just seeing the result of
System.out.println(data);
which has your client print the message it just sent.
In order for the client to accept input from the user and read messages from the server at the same time, you should probably use two threads on the client. One thread can just be the client thread you already wrote, since it takes care of accepting input from the user. The other thread should look something like this:
public class ClientReaderThread extends Thread {
Socket socket;
ClientReaderThread(Socket socket) {
this.socket = socket;
}
public void run() {
try (BufferedReader serverReader = new BufferedReader(
new InputStreamReader(socket.getInputStream()))){
String fromServer = serverReader.readLine();;
while(fromServer != null) {
if (fromServer.equals("stop"))
break;
System.out.println(fromServer);
fromServer = serverReader.readLine();
}
} catch (IOException e) {
System.out.println("Client error! Got exception: " + e);
}
}
}
(Note that I use the try-with-resources statement to construct the reader, which takes care of closing it when the client stops).
Then in your main client class, start both threads with the same socket:
Multiclient() throws IOException
{
socket = new Socket("127.0.0.1", 1036);
System.out.println(socket);
Mythreadc my = new Mythreadc(socket);
ClientReaderThread reader = new ClientReaderThread(socket);
my.start();
reader.start();
}
Problem two: Your server only reads and echoes a single line from each client, because the socket thread that handles each client (Mythread) doesn't contain a loop. With your setup of creating a single thread per client, run() only gets called once per client, so that run() method needs to handle every message that client sends.
Here's how the run() method in the server's thread should look:
public void run() {
try (BufferedReader inStream = new BufferedReader(
new InputStreamReader(socket.getInputStream()))){
String data = inStream.readLine();
while(data != null) {
if(data.equals("stop"))
break;
broadcast(data);
data = inStream.readLine();
}
}
catch(Exception e){
System.out.println("Run exception "+e);
} finally {
al.remove(socket); //This is important to do
}
}
I made an additional important change here: at the end of the run() method, when either the client disconnected or an exception happened, the thread removes its socket from the ArrayList. This ensures that other server threads, which all reference the same ArrayList, don't try to broadcast to the socket of a client that has disconnected. If you neglect to do this, you'll get an exception when a client sends a message to the server after another client has disconnected.
Miscellaneous notes
As I mentioned in my comment, you should give al a type of ArrayList<Socket> inside the thread class, and use a for-each loop instead of an Iterator to iterate over it in broadcast().
I'm using BufferedReader instead of DataInputStream to read from the socket. That's because DataInputStream.readUTF() and writeUTF() are deprecated, and have been replaced with BufferedReader.readLine() and PrintWriter.println().
The streams like dis and dos don't need to be instance variables in your thread classes, since they are only ever used inside the run() method. They can be local variables inside run(), like I did with inStream in my new run() method.
I think you just missed passing the ArrayList of Sockets Users Currently Connected to The Server to the thread
and Instead of Posting your Server Class You have just posted Client Program 2 times anyway ,
Your ServerClass should be build in this way : -
As soon as ServerClass recieves the request from any client, Server Class should add the Socket into ArrayList and create New Thread and just pass both to the MyThread Class
Edit :
It seems you haven't written code for Displaying the data you will get from the server .
At Client Side for Sending the Message You can simple write that in Main Thread that is under Your Client Class's Main Mehtod
You actually needed Thread at client side not for sending the message but rather for Listening the Message from the server,
because you never known when anyone can send you the message but you will always know when you want to send message to anybody connected to this chat App
Now coming to the Coding Part :
Client Class
public class Multiclient {
Socket socket;
DataInputStream dis;
DataOutputStream dos;
Multiclient() throws IOException
{
socket = new Socket("127.0.0.1", 1036);
System.out.println(socket);
Mythreadc my = new Mythreadc(socket);
my.start();
/**
* Here write out the code for taking input from Standard Console
*/
BufferedReader br = null;
try{
br = new BufferedReader(new InputStreamReader (System.in));
dos = new DataOutputStream(socket.getOutputStream());
String data = "";
do{
data = br.readLine();
dos.writeUTF(data);
System.out.println(data);
dos.flush();
}
while(!data.equals("stop"));
}
catch(Exception e)
{
System.out.println("Client input "+e);
}
}
Client Thread
try{
String data ="";
dis = new DataInputStream(socket.getInputStream());
while(data.equalsIgnorCase("stop")){
data = dis.readUTF();
System.out.println("Server Message : "+data);
}
}
catch(Exception e){
System.out.println("Run "+e);
}
Client Thread is not complete but i think this information is sufficient enough .
Hope It help you out , Your problem do remind me of College Days :)
There's a million examples on using Java sockets out there - and every one is the same!
Every one shows a client socket being created, some text being sent, and the socket closed.
I am writing some test code. I want my client to loop round and send quite a few messages. It seems silly to close the client socket each time and re-create, so I thought I would just create one client socket, loop round and send data on the same socket. The thing is though - my server socket does not print out what it has received until the last message has been sent by the client and the client socket closed.
Server:
Socket sock;
ClientConnection client;
ServerSocket ss = new ServerSocket(portNumber);
ss.setSoTimeout(0); // 0=infinite
while (true) {
sock = ss.accept();
client = new ClientConnection(sock);
new Thread(client).start();
// ClientConnection reads from sock, prints, and closes sock
}
ClientConnection (a separate class on the Server side):
public class ClientConnection implements Runnable
{
private Socket m_socket;
private BufferedReader m_in = null;
public ClientConnection(Socket socket)
{
m_socket = socket;
try {
InputStream inStream = socket.getInputStream();
m_in = new BufferedReader(new InputStreamReader(inStream));
}
catch (IOException ioe) {
ioe.printStackTrace();
}
}
public String getMessage()
{
String line = null;
StringBuffer completeMessage = new StringBuffer();
try {
while ((line = m_in.readLine()) != null)
{
completeMessage.append(line);
}
}
catch (IOException ioe) {
ioe.printStackTrace();
return "";
}
return completeMessage.toString();
}
public void run()
{
try {
String message = getMessage();
System.out.println("Received: " +message);
}
finally
{
try {
m_socket.close();
}
catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
}
Client:
socket = new java.net.Socket(m_destination, m_portNumber);
outputStream = socket.getOutputStream();
printStream = new java.io.PrintStream(outputStream);
while (more-stuff-to-send)
{
printStream.print(text);
printStream.print("\n");
printStream.flush();
}
prinStream.close();
socket.close();
ClientConnection is created by the server when I start the client, but it does not print what has been sent until the client is done sending.
I feel like I'm missing the point somewhere along the line. Chat examples are quite common, so if I had a chat client then every message it wanted to send to a chat server it would create a client socket, send the message, and close the socket? Just doesn't seem right somehow.
Thank you.
client = new ClientConnection(sock);
You are passing the socket in constructor.
so you shouldn't do:
socket = new java.net.Socket(m_destination, m_portNumber);
just cache that vatiable from contructor as : this.sock = sock;
getting the reader and the writer is ok, also the server is ok.
I would use a Vector to be synchromized queue for sending messages, and the while (more-stuff-to-send) loop would check the queue and id empty than sleep, if has something to send, than pop the first and sent it while he must do stuff, or socket is closed my the client.