Client-server two way communication - java

I wrote simple client serwer, but unfortunately, I did it so chaotic and poorly that I decided to write everything from scratch. I want to write to communicate in both directions with the ability to disconnect and connect a new client. It means the client or the server sends a message and an appropriate one reads it. At the beginning all works but when i want to close client i get two errors:
java.net.SocketException: Socket closed readSocketData()
java.net.SocketException: Socket closedwriteData(String data)
Of course I understand what those errors means , but I do not understand why they show up because i have a while loop in which i check if the client is connected. Later when i try to connect a new client everything is falling apart.
I wrote 3 classes client, server and communication. Client and server inherits from communication (methods for opening and reading data streams). It all looks like that:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server extends Communication{
ServerSocket serverSocket;
Socket listener;
boolean listenerLife;
public Server(int port) {
try {
serverSocket = new ServerSocket(port);
} catch (IOException e) {
System.out.println(e);
}
}
public void startListener(){
while (true){
try {
listener = serverSocket.accept();
listenerLife = true;
} catch (IOException e) {
System.out.println(e);
}
openWriter(listener);
openReader(listener);
writeServerDataThread();
new Thread(new Runnable() {
#Override
public void run() {
readData();
}
}).start();
}
}
public void writeServerDataThread(){
openLocalReader();
new Thread(new Runnable() {
#Override
public void run() {
while (true){
String data = readLocalData();
writeData(data);
}
}
}).start();
}
public void readData(){
while (listenerLife){
String data = readSocketData();
if("exit".equals(data) || data == null){
try {
listenerLife = false;
listener.close();
} catch (IOException e) {
System.out.println(e);
}
}
else {
System.out.println(data);
}
}
}
public void writeData(String data){
try {
writer.writeBytes(data + '\n');
writer.flush();
} catch (IOException e) {
System.out.println(e);
}
}
public static void main(String[] args) {
Server server = new Server(8080);
server.startListener();
}
}
import java.io.IOException;
import java.net.Socket;
public class Client extends Communication{
Socket clientSocket;
boolean clientLive;
public Client(String hostName, int port) {
try {
clientSocket = new Socket(hostName, port);
clientLive = true;
} catch (IOException e) {
System.out.println(e + "Client(String hostName, int port)");
}
}
public boolean closeConnection(String data){
if("exit".equals(data) || data == null){
try {
writeData("Zamykam klienta");
clientSocket.close();
clientLive = false;
return false;
} catch (IOException e) {
System.out.println(e + "closeConnection(String data)");
}
}
return true;
}
public void readClientData(){
new Thread(new Runnable() {
#Override
public synchronized void run() {
openLocalReader();
while (!clientSocket.isClosed()){
String data = readLocalData();
if(closeConnection(data)){
writeData(data);
}
}
}
}).start();
}
public void readServerDataThread(){
new Thread(new Runnable() {
#Override
public synchronized void run() {
while (!clientSocket.isClosed()){
String data = readSocketData();
if(closeConnection(data)){
System.out.println(data);
}
}
}
}).start();
}
public void writeData(String data){
try {
writer.writeBytes(data + '\n');
writer.flush();
} catch (IOException e) {
System.out.println(e + "writeData(String data)");
}
}
public static void main(String[] args) {
final Client client = new Client("localhost", 8080);
client.openReader(client.clientSocket);
client.openWriter(client.clientSocket);
client.readServerDataThread();
client.readClientData();
}
}
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class Communication {
BufferedReader reader;
BufferedReader localReader;
DataOutputStream writer;
public void openReader(Socket incomingSocket){
try {
reader = new BufferedReader(new InputStreamReader(incomingSocket.getInputStream()));
} catch (IOException e) {
System.out.println(e);
}
}
public void openWriter(Socket incomingSocket){
try {
writer = new DataOutputStream(incomingSocket.getOutputStream());
} catch (IOException e) {
System.out.println(e);
}
}
public void openLocalReader(){
localReader = new BufferedReader(new InputStreamReader(System.in));
}
public String readLocalData(){
String data = null;
try {
data = localReader.readLine();
} catch (IOException e) {
System.out.println(e + " readLocalData()");
}
return data;
}
public String readSocketData(){
String data = null;
try {
data = reader.readLine();
} catch (IOException e) {
System.out.println(e + " readSocketData()");
}
return data;
}
}

java.net.SocketException: Socket closed readSocketData()
java.net.SocketException: Socket closed writeData(String data)
Of course I understand what those errors means
They mean you closed the socket and continued to use it.
but I do not understand why they show up because i have a while loop in which i check if the client is connected.
No you don't. You have a while loop in which you check if the client socket is still open, which isn't the same thing at all ... but in any case that doesn't prevent you from using a closed socket inside the loop, for example after you close it in closeConnection(), whose return value being back to front from what it should be is doubtless causing confusion, and which is called by two threads as far as I can tell.

Related

How to send a message through all Threads?

At the moment i have a Server and a Client, and when the Client is connected to the Server, a Thread is created to handle all the resposnses from the respective Client and also to send any needed answers. My problem now is that i need to be able to send a message through every existent Thread to their respective Client.
I was thinking of doing it like this:
public class ServerThread extends Thread {
//ignore most of the constructor, just things i need
public ServerThread(Socket socket, int threadId, Manager manager) throws Exception {
try {
this.socket = socket;
this.threadId=threadId;
this.manager=manager;
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
manager.addThread(); //This should add this Thread to the Collection in the Manager class
} catch (IOException ex) {
throw new Exception("Error", ex);
}
}
public void notify(String message){
// Do something
}
//In the end of the thread i would call manager.removeThread to remove the Thread from the Collection
}
public class Manager {
private //Thread Collection here
public Manager(){
//Initialize the collection;
}
public void addThread(){
//Add thread
}
public void removeThread(){
//Remove Thread
}
}
If this is a viable option to handle this, what Collection would i need to store the Threads and also, what would the notify(String message) method look like? It would need to call a method in Manager that would send a message to every Thread right?
If you want to create a multi-client server what is usually recommended is that in the main thread (or a separate thread) of the server class, the server will be accepting incoming Sockets (client) and with every socket accepted a new thread is created to service that client and it is better to have the service as a separate class that implements runnable or extends thread. Each service thread will be waiting for input from the client it is associated with and replying according to the client's request.
If you are looking to broadcast data to all the connected clients then what you need is to have an ArrayList that stores the client service objects and then loop over it, with every loop you send data to one of the connected clients but you have to make sure that you remove the clients that disconnected from the ArrayList otherwise it will start throwing exceptions.
usually, client service classes have the accepted socket, an input stream, and an output stream.
here is an example of a multiclient echo server that I have made maybe it will help.
public class TcpServer {
public TcpServer(){
ServerSocket server = null;
try{
server = new ServerSocket(9991);
while(!server.isClosed()){
Socket acceptedSocket = server.accept();
EchoService service = new EchoService(acceptedSocket);
service.start();
}
}catch (IOException e){
e.printStackTrace();
} finally {
if(server!=null) {
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args){
new TcpServer();
}}
This is the service class:
public class EchoService extends Thread {
private Socket acceptedSocket;
private DataInputStream is;
private DataOutputStream os;
public EchoService(Socket acceptedSocket) {
try {
this.acceptedSocket = acceptedSocket;
is = new DataInputStream(acceptedSocket.getInputStream());
os = new DataOutputStream(acceptedSocket.getOutputStream());
} catch (IOException e) {
try {
if (this.acceptedSocket != null)
acceptedSocket.close();
if(is != null)
is.close();
if(os != null)
os.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
#Override
public void run() {
super.run();
try {
while (!acceptedSocket.isClosed()) {
String usrMsg = is.readUTF();
String serverMsg = "server: "+usrMsg;
os.writeUTF(serverMsg);
os.flush();
}
} catch (IOException e) {
try {
if(this.acceptedSocket != null)
acceptedSocket.close();
if(is != null)
is.close();
if(os != null)
os.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}}
This is the same example but with the Broadcast feature included
Server class:
package TCP;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class TcpServer {
public static ArrayList<EchoService> connectedServices;
public TcpServer(){
ServerSocket server = null;
try{
server = new ServerSocket(9991);
System.out.println("server started");
connectedServices = new ArrayList<>();
while(!server.isClosed()){
Socket acceptedSocket = server.accept();
System.out.println("client connected: "
+acceptedSocket.getInetAddress());
EchoService service = new EchoService(acceptedSocket);
service.start();
}
}catch (IOException e){
e.printStackTrace();
} finally {
if(server!=null) {
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args){
new TcpServer();
}
public static void removeConnectedService(EchoService client) {
boolean removed = connectedServices.remove(client);
System.out.println("client has been removed"+
client.getAcceptedSocket().getInetAddress()+", "+removed);
}
public static void broadCastMsg(long id, String usrMsg) throws IOException {
for(EchoService client: connectedServices){
if(client.getId()!=id)
{
String serverMsg = "server broadcast: " + usrMsg;
client.getOs().writeUTF(serverMsg);
client.getOs().flush();
}
}
}
}
service class:
package TCP;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
public class EchoService extends Thread {
private Socket acceptedSocket;
private DataInputStream is;
private DataOutputStream os;
public EchoService(Socket acceptedSocket) {
try {
this.acceptedSocket = acceptedSocket;
is = new DataInputStream(acceptedSocket.getInputStream());
os = new DataOutputStream(acceptedSocket.getOutputStream());
} catch (IOException e) {
try {
if (this.acceptedSocket != null)
acceptedSocket.close();
if(is != null)
is.close();
if(os != null)
os.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
#Override
public void run() {
super.run();
try {
TcpServer.connectedServices.add(this);
while (!acceptedSocket.isClosed()) {
String usrMsg = is.readUTF();
if(usrMsg.contains("BROADCAST"))
TcpServer.broadCastMsg(this.getId(),usrMsg);
else {
String serverMsg = "server: " + usrMsg;
os.writeUTF(serverMsg);
os.flush();
}
}
} catch (IOException e) {
TcpServer.removeConnectedService(this);
try {
if(this.acceptedSocket != null)
acceptedSocket.close();
if(is != null)
is.close();
if(os != null)
os.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
public DataInputStream getIs() {
return is;
}
public DataOutputStream getOs() {
return os;
}
public Socket getAcceptedSocket() {
return acceptedSocket;
}
}
Server output:
client 1 output:
client 2 output:
client 3 output:
I would create a static method getInstance(int threadId) in ServerThread.
Inside this, you create a syncronized and static Map (see class Collections).
In notify just navigate over the map and send your messages to your ServerThread instances.
(note: if it's a TreMap it will be sorted by the key)

Java multithreaded server - High CPU Utilization and java.net.SocketException: socket closed [duplicate]

This question already has an answer here:
java.net.SocketException: socket closed TCP Client Server Communication [duplicate]
(1 answer)
Closed 5 years ago.
This is the first java socket/multithreaded application that I write, therefore I would like to apologize for the atrocious code that you are about to witness.
Anyway, most of you will probably regard this code as being basic, a standard server that allows connection from more clients at a time. Also, the server has an interface with just a StopServer button, which closes the server, meanwhile the Client doesn't do anything else than just connect to the server and then disconnect afterwards.
Now, if I simply run the server class, it's ok, nothing 'bad' happens and when I close it, it closes fine, however:
1: If I run the server class, and then I run the client class once, let the client disconnect, and then try to close the server, I get the error:
java.net.SocketException: socket closed
2: Each client will add about ~30-35% of CPU utilization in just a brief run, and that utilization will remain at the "Java(TM) Platform SE Binary" process, for as long as the server continues to run. If I let a client be connected to the server for, let's say 30 seconds, the CPU utilization will reach 100%.
Also, I did a little research and I know that the "socket closed exception" means that you closed the socket, and then continued to try to use it, and also there's probably something wrong with how the server handles the disconnected clients.
Here's the code:
Server
import java.sql.*;
import java.net.*;
import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Server extends JFrame
{ private Connection con;
private static int port = 44444;
private boolean serverKeepGoing;
private static int uniqueId;
private ArrayList<ClientThread> al;
private ServerSocket serverSocket;
public Scanner keyboard = new Scanner(System.in);
public static void main(String[] args) throws IOException
{ Server server = new Server(port);
server.start();
}
public void ServerClose()
{
serverKeepGoing = false;
try
{
for(int i = 0; i < al.size(); ++i)
{ ClientThread tc = al.get(i);
try
{
tc.in.close();
tc.out.close();
tc.socket.close(); }
catch(IOException e) { e.printStackTrace(); }
serverSocket.close();}
}catch(Exception e) { e.printStackTrace(); }
}
public Server (int port)
{
serverInterface();
al = new ArrayList<ClientThread>();
}
public void start()
{ serverKeepGoing = true;
try
{ serverSocket = new ServerSocket(port);
System.out.println("Server is running!");
while(serverKeepGoing)
{ Socket socket = serverSocket.accept(); // accept connection. LINE 65
// ^ALSO :java.net.SocketException: socket closed
// if I was asked to stop
if(!serverKeepGoing)
{ ServerClose(); break;}
ClientThread t = new ClientThread(socket); // make a thread of it
al.add(t); // save it in the ArrayList
t.start();
}
ServerClose(); // means the server has got to be closed
}catch (IOException e) { e.printStackTrace(); System.out.println("Error in method start"); }
}
public synchronized void remove(int id) {
// scan the array list until we found the Id
for(int i = 0; i < al.size(); ++i) {
ClientThread ct = al.get(i);
// found it
if(ct.id == id) {
al.remove(i);
return;
}
}
}
class ClientThread extends Thread
{ // the socket where to listen/talk
Socket socket;
BufferedReader in;
PrintWriter out;
boolean clientKeepGoing;
// my unique id (easier for deconnection)
int id;
public ClientThread(Socket socket)
{ id = ++uniqueId;
this.socket = socket;
try
{
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
}
catch (IOException e) { return; }
}
public void run()
{
boolean clientKeepGoing = true;
while(clientKeepGoing)
{ try
{
}catch(Exception e){ e.printStackTrace(); }
}
// remove myself from the arrayList containing the list of the
// connected Clients
remove(id);
close();
}
// try to close everything
private void close()
{ clientKeepGoing = false;
try {
if(out != null) out.close();
}
catch(Exception e) {}
try {
if(in != null) in.close();
}
catch(Exception e) {};
try {
if(socket != null) socket.close();
}
catch (Exception e) {}
}
}
public void serverInterface(){
JFrame frame = new JFrame("Server");
frame.setLayout(null);
int windowWidth = 300;
int windowHeight = 400;
frame.setBounds(250, 150, windowWidth, windowHeight);
JButton stopServer = new JButton("Stop server");
stopServer.setFocusable(false);
stopServer.setBounds(60, 275, 175, 20);
frame.add(stopServer);
stopServer.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
ServerClose();
System.exit(1);
}
});
frame.setResizable(false);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setVisible(true);
}
public void windowClosing(WindowEvent e)
{ ServerClose();
System.exit(1);
}
public void windowClosed(WindowEvent e) {}
public void windowOpened(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
}
The 'java.net.SocketException: socket closed' is on line 65 of the code above.
Client
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
public class Client
{ private BufferedReader in;
private PrintWriter out;
private Socket socket;
private int port;
private String server;
public static void main(String[] args)
{ int portNumber = 44444;
String serverAddress = "localhost";
Client client = new Client(serverAddress, portNumber);
if(!client.start())
return;
}
public Client(String server, int port)
{ this.server = server;
this.port = port;
}
public boolean start()
{ // try to connect to the server
try {
socket = new Socket(server, port);
}
// if it failed not much I can do
catch(Exception ec) {
System.out.println("Error connectiong to server:" + ec);
ec.printStackTrace();
return false;
}
try
{
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);;
}
catch (IOException eIO) {
System.out.println("Exception creating new Input/output Streams: " + eIO);
eIO.printStackTrace();
return false;
}
// creates the Thread to listen from the server
new ListenFromServer().start();
// success we inform the caller that it worked
return true;
}
class ListenFromServer extends Thread
{
public void run()
{ while(true)
{
disconnect() ;
break;
}
}
}
public void disconnect()
{ try {
if(in != null) in.close();
}
catch(Exception e) {} // not much else I can do
try {
if(out != null) out.close();
}
catch(Exception e) {} // not much else I can do
try{
if(socket != null) socket.close();
}
catch(Exception e) {} // not much else I can do
}
}
Note that this is just a fragment of the whole application that I am currently building, I tried to post only what had to do with the Server-Client communication, so I deleted everything else, I'm saying this in case you see something that maybe doesn't have any purpose, I probably omitted to delete it
I see that the question got marked as duplicate, which I consider to be unfair. Firstly, in the 'similar' question, the problem was obvious, the outpot stream was closed, which closed the socket, but the socket had still been used, meanwhile, my program closes everything alltoghether and also has the CPU problem I mentioned, for which I cannnot get any answer from the so called 'similar' question.
The high CPU utilization is because your client threads aren't doing anything else besides burning the CPU with their empty loops. As for the SocketException, it works as planned, so catch it and handle it.

java socket multiple clients not receiving messages

i am making a java socket chat program and i made it compatible for multiple connections and when a user joins it doesn't send the message "[user] Joined" to all clients just to the one that connected but i have a thread for each client if anyone can tell me why it is only sending the message to the user that recently joined i would greatly appreciate it. Here is the server code
import java.io.*;
import java.net.*;
import java.util.ArrayList;
public class server {
public ObjectInputStream input;
public ServerSocket server;
public Socket s;
public ObjectOutputStream output;
public ArrayList<Socket> users = new ArrayList<Socket>();
public class Accept implements Runnable {
public void run() {
try {
server = new ServerSocket(55555, 100);
} catch (IOException e) {
e.printStackTrace();
}
while(true) {
try {
s = server.accept();
users.add(s);
new EchoThread(s).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public class EchoThread extends Thread {
private Socket sock;
public EchoThread(Socket s) throws IOException {
this.sock = s;
output = new ObjectOutputStream(sock.getOutputStream());
}
public void run() {
System.out.println(sock.getInetAddress() + " Connected");
try {
for(Socket s: users) {
output.writeObject(s.getInetAddress() + " Connected");
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
server() throws IOException {
Thread t = new Thread(new Accept());
t.start();
}
public static void main(String[] args) throws IOException {
new server();
}
}
So,
Every time someone connects to the server, u create a new EchoThread.
Each User has his own EchoThread.
Your Server role is to manage all the EchoThreads and Sockets.
output.writeObject(s.getInetAddress() + " Connected");
This only sends a message to ONE user.
Your Server should have a List of Sockets and send messages to every Sockets
public ArrayList<Socket> users = new ArrayList<Socket>();
public ArrayList<ObjectOutputStream> outputs = new ArrayList<ObjectOutputStream>();
public class Accept implements Runnable {
public void run() {
try {
server = new ServerSocket(55555, 100);
} catch (IOException e) {
e.printStackTrace();
}
while(true) {
try {
s = server.accept();
users.add(s);
outputs.add(new ObjectOutputStream(s.getOutputStream()));
for (ObjectOutputStream o: outputs) {
o.writeObject(s.getInetAddress() + " has connected");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

Server reply to Client message failing due to closed socket - Java Client-Server example

I'm creating this little client-server program to learn about sockets, and so far, I'm having a bit of trouble. For the purpose of this post, I consolidated the code into a single class. And the code will compile. (So it will show the same errors I get)
When the client connects to the server, the server socket properly creates a socket on the server-side. The Client then successfully sends a message to the server, but when the server tries to send a response to the client, there is an error saying the socket is closed.
Main.java
package main;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Hashtable;
public class Main {
boolean running = true;
public static void main(String[] args){
new Main().start();
}
public void start(){
new Thread(new ConnectionListener()).start(); //Starts Server
try {
connectToServer();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public class ConnectionListener implements Runnable{
public void run() {
ServerSocket ss = null;
try {
ss = new ServerSocket(31415);
}catch (BindException e) {
e.printStackTrace();
return;
} catch (IOException e) {
e.printStackTrace();
return;
}
while(running){
try {
Socket sock = ss.accept();
ServerConnection c = new ServerConnection(sock);
c.start();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void connectToServer() throws UnknownHostException, IOException{
//Create Connection to Server
Socket socket = new Socket("localhost",31415);
ClientConnection cc = new ClientConnection(socket);
cc.start();
//Send First Message to Server
Hashtable<Integer, String> htt = new Hashtable<Integer, String>();
htt.put(0,"Hello, This is a Chat Test");
Message m = new Message(Message.Type.CHAT,htt);
cc.sendMessage(m);
}
public class ServerConnection{
Socket sock;
boolean connected = true;
public ServerConnection(Socket sock){
this.sock = sock;
}
public void start() {
new Thread(new RequestListener()).start();
}
private void handleMessage(Message m){
System.out.println("Server : Handle message " + m.type.toString());
}
public void disconnect(){
System.out.println("Disconnect user");
}
public void sendMessage(Message m){
try {
ObjectOutputStream os = new ObjectOutputStream(sock.getOutputStream());
os.writeObject(m);
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
class RequestListener implements Runnable{
public void run() {
ObjectInputStream is = null;
try {
is = new ObjectInputStream(sock.getInputStream());
while(connected){
try {
Message m = (Message)
is.readObject(); //EOFException
handleMessage(m);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch(SocketException e){
disconnect();
e.printStackTrace();
break;
}catch (IOException e) {
//e.printStackTrace(); //EOFException Here
}
}
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
public class ClientConnection {
private Socket socket;
private boolean connected = true;
public ClientConnection(Socket socket) {
this.socket = socket;
}
public void start(){
new Thread(new RequestListener()).start();
}
public void sendMessage(Message m){
try {
ObjectOutputStream os = new ObjectOutputStream(socket.getOutputStream());
os.writeObject(m);
os.flush();
os.close();
} catch (IOException e) {
System.out.println("Error Sending Message");
e.printStackTrace();
}
}
public void close() throws IOException{
Message m = new Message(Message.Type.DISCONNECT,null);
sendMessage(m);
socket.close();
}
private void handleMessage(Message m){
System.out.println("Client : Handle message " + m.type.toString());
}
class RequestListener implements Runnable{
public void run() {
ObjectInputStream is = null;
try {
System.out.println(socket.isConnected()); //true
System.out.println(socket.isClosed()); //false
InputStream iss = socket.getInputStream();
is = new ObjectInputStream(iss); //socketClosedException
while(connected){
try {
Message m = (Message)is.readObject();
handleMessage(m);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch(SocketException e){
System.out.println("Server Disconnected");
break;
}catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
Message.java
package main;
import java.io.Serializable;
import java.util.Hashtable;
public class Message implements Serializable{
public enum Type{
LOGIN, PM, DISCONNECT, INCORRECT_LP,CORRECT_LP, UPDATE_USERLIST, CHAT, INCORRECT_VERSION
}
public Type type;
Hashtable ht;
public Message(Type type, Hashtable ht){
this.type = type;
this.ht = ht;
}
public Object get(Object o){
return ht.get(o);
}
}
There's nothing 'random' about it.
Closing the input or output stream of a Socket closes the other stream and the Socket.
In this case you are closing the ObjectOutputStream you have wrapped around the socket's output stream, which closes that output stream, which closes the socket's input stream and the socket.

Simple Java Threaded TCP Server thread

/*main method*/
Server server = new Server(tcpPort);
new Thread(server).start();
try {
Thread.sleep(1000*60); /* 60 seconds*/
} catch (InterruptedException e) {
e.printStackTrace();
}
server.stop;
...
This is the code I've written. A Server thread is started, and runs for 60 seconds. How do I change this to run infinitely, ending when a user enters Enter via a BufferedReader or something.
I've tried it with
while(!input.equals("")) { /* just pseudocoded here...*/
Thread.sleep(10);
}
but this will my Server stop from working correctly. My clients won't even connect to it anymore. Have I made a design mistake or is this an easy problem to solve?
Try this basic Chatting Server that I wrote. This server simply keeps running in loop and broadcast the message send by the clients to all the other clients associated with this server.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class Server {
// ///----------------------------------------Instance Variable Fields
ServerSocket ss = null;
Socket incoming = null;
// ///----------------------------------------Instance Variable Fields
// ///---------------------------------------- static Variable Fields
public static ArrayList<Socket> socList = new ArrayList<Socket>();
// ///---------------------------------------- static Variable Fields
public void go() {
try {
ss = new ServerSocket(25005);
while (true) {
incoming = ss.accept();
socList.add(incoming);
System.out.println("Incoming: " + incoming);
new Thread(new ClientHandleKaro(incoming)).start();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
ss.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class ClientHandleKaro implements Runnable {
InputStream is = null;
OutputStream os = null;
InputStreamReader isr = null;
BufferedReader br = null;
PrintWriter pw = null;
boolean isDone = false;
Socket sInThread = null;
public ClientHandleKaro(Socket sxxx) {
this.sInThread = sxxx;
}
#Override
public void run() {
if (sInThread.isConnected()) {
System.out.println("Welcamu Clienta");
System.out.println(socList);
}
try {
is = sInThread.getInputStream();
System.out.println("IS: " + is);
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
os = sInThread.getOutputStream();
pw = new PrintWriter(os, true);
String s = new String();
while ((!isDone) && (s = br.readLine()) != null) {
String[] asx = s.split("-");
System.out.println("On Console: " + s);
// pw.println(s);
Thread tx = new Thread(new ReplyKaroToClient(s,
this.sInThread));
tx.start();
if (asx[1].trim().equalsIgnoreCase("BYE")) {
System.out.println("I am inside Bye");
isDone = true;
}
}
} catch (IOException e) {
System.out.println("Thanks for Chatting.....");
} finally {
try {
Thread tiku = new Thread(new ByeByeKarDo(sInThread));
tiku.start();
try {
tiku.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Accha to hum Chalte hain !!!");
System.out.println(socList);
br.close();
pw.close();
sInThread.close();
} catch (IOException e) {
}
}
}
}
class ReplyKaroToClient implements Runnable {
public String mString;
public Socket mSocket;
public ReplyKaroToClient(String s, Socket sIn) {
this.mString = s;
this.mSocket = sIn;
}
#Override
public void run() {
for (Socket sRaW : socList) {
if (mSocket.equals(sRaW)) {
System.out.println("Mai same hun");
continue;
} else {
try {
new PrintWriter(sRaW.getOutputStream(), true)
.println(mString);
} catch (IOException e) {
System.out.println("Its in Catch");
}
}
}
}
}
class ByeByeKarDo implements Runnable {
Socket inCom;
public ByeByeKarDo(Socket si) {
this.inCom = si;
}
#Override
public void run() {
try {
new PrintWriter(inCom.getOutputStream(), true)
.println("You have Logged Out of Server... Thanks for ur Visit");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new Server().go();
}
}
Start with this SO thread: How to create a basic Java Server? . It will give you an example how to write a very simple server.
Key thing to note there is the serverSocket.accept() . It will block - in other words it will WAIT forever for a client to connect, or it will fail in the case of some error. Once a client is connected, you will get a clientSocket that you can use to read what client wrote, and also write to it.
It is really a good starting point for understanding Java network programming. However, I recommend you read more about this topic. Something like this: http://beej.us/guide/bgnet/

Categories