Cannot get elements from Vector from other class (Thread) - java

i have this Class (my Server start Class), here i create with every new Client a new Thread for him. After the Thread was createt, i add him to the Vector (list) to keep Track of active users and connections, so that i can send messages to a specific user. But i cant Access the Vector-List from my Thread (its the class below). Can you explain me, how i can do this? I have a private list and public setter and getter methods but i always get the size 1 from the Vector. But i testet it, if i connect with more then one client there are multiple Threads with different socket creates. I can add Entrys to the vector if i do it manuel in my server start class.
package securemessageserver;
public class SecureMessageServer {
private Vector<SecureMessageServerClientThread> userList = new Vector();
private SSLServerSocket sslserversocket;
int port = 9999;
private Boolean isRunning=true;
SSLSocket sslsocket;
private synchronized void loadCertificat(){
try {
URL url = this.getClass().getResource("/securemessageserver/keystore.jks");
File file = new File(url.toURI());
System.setProperty("javax.net.ssl.keyStore", "C:/keystore.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "Schelkan1994");
//System.setProperty("javax.net.debug","all");
System.out.println("Certifikat geladen");
} catch (URISyntaxException ex) {
Logger.getLogger(SecureMessageServer.class.getName()).log(Level.SEVERE, null, ex);;
stopServer();
}
}
private synchronized void createSocket(){
try {
SSLServerSocketFactory sslserversocketfactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
sslserversocket = (SSLServerSocket) sslserversocketfactory.createServerSocket(port);
System.out.println("Socket erstellt mit "+port);
} catch (IOException ex) {
Logger.getLogger(SecureMessageServer.class.getName()).log(Level.SEVERE, null, ex);
stopServer();
}
}
private synchronized void startServer(SSLServerSocket sslserversocket){
while(isRunning){
try {
System.out.println("Akzeptiere Verbindungen");
sslsocket = (SSLSocket) sslserversocket.accept();
SecureMessageServerClientThread client = new SecureMessageServerClientThread(sslsocket);
startNewClient(client);
userList.add(client);
} catch (IOException ex) {
Logger.getLogger(SecureMessageServer.class.getName()).log(Level.SEVERE, null, ex);
stopServer();
}
}
}
public synchronized void startNewClient(SecureMessageServerClientThread th){
new Thread(th).start();
}
public synchronized void stopServer(){
isRunning=false;
}
public synchronized SSLServerSocket getServerSocket(){
if(sslserversocket!=null){
return this.sslserversocket;
}
return null;
}
public synchronized void addThreadToList(SecureMessageServerClientThread thread){
userList.add(thread);
}
public synchronized void getAllThreadFromList(){
System.out.println("Size: "+userList.size());
}
public synchronized String getUserName(){
return userList.get(0).getUserOfThread();
}
public synchronized void deleteThreadFromList(SecureMessageServerClientThread thread){
userList.remove(thread);
}
public synchronized void getUserNameOfAllThreads(){
for(int i=0;userList.size()>i;i++){
System.out.println(userList.get(i).getUserOfThread());
}
}
public static void main(String[] args){
SecureMessageServer server = new SecureMessageServer();
server.loadCertificat();
server.createSocket();
server.startServer(server.sslserversocket);
}
}
And hier ist the other class (My Thread Class) instanze of this class if always createt if new client connect to keep track of the connection and to perform input and output operations. But i dont get the right value from the Vector in the other class ... Do you see my error? Thanks for help
public class SecureMessageServerClientThread implements Runnable{
private SSLSocket socket;
private String userName;
boolean isRunning=true;
SecureMessageServer server = new SecureMessageServer();
public SecureMessageServerClientThread(SSLSocket socket){
this.socket=socket;
}
private ObjectInputStream sInput;
private ObjectOutputStream sOutput;
#Override
public void run() {
System.out.println("Client mit Socket is Running: "+socket);
while(isRunning){
try {
sInput = new ObjectInputStream(socket.getInputStream());
SecureMessageServerClientMessage msg = (SecureMessageServerClientMessage) sInput.readObject();
if(msg.getType()==0){
System.out.println("All Threads:");
server.getAllThreadFromList();
}else if(msg.getType()==1){
System.out.println(msg.getMessage());
}else if(msg.getType()==2){
Thread.sleep(1000);
socket.close();
this.stopThread();
}else{
System.out.println("Unbekannter Nachrichtentyp");
}
} catch (IOException ex) {
Logger.getLogger(SecureMessageServerClientThread.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(SecureMessageServerClientThread.class.getName()).log(Level.SEVERE, null, ex);
} catch (InterruptedException ex) {
Logger.getLogger(SecureMessageServerClientThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public void stopThread(){
isRunning=false;
// sOutput = new ObjectOutputStream(socket.getOutputStream());
}
public String getUserOfThread(){
return this.userName;
}
public void getUserList(){
server.getAllThreadFromList();
}
}

In SecureMessageServerClientThread, you create a new Server instance with SecureMessageServer server = new SecureMessageServer();.
This means that when you call server.getAllThreadFromList() in getUserList, you're getting the list from the server you just created which has no clients.
The Client thread should instead take the server instance as a parameter:
SecureMessageServer server;
public SecureMessageServerClientThread(SSLSocket socket, SecureMessageServer server){
this.socket=socket;
this.server=server;
}
And in the Server, you should pass this to the new client instance:
SecureMessageServerClientThread client = new SecureMessageServerClientThread(sslsocket, this);

Well, if it is private you obviously can't access from another class. Make it protected and make both classes be in same package.

Related

Java - Multithread Server to serve multiple concurrent clients

I've been trying to make the code below to have multiple clients communicate with the same server.
Currently, it works one client at a time with the server but it seems to be that when the second client opens, code stops at new ObjectInputStream(connection.getInputStream()); in the Class 3 (client) - see below.
I've tried making the inputstream object transient to be shared in different threads but it didn't work, nor with making runClient method synchronized.
If I were to implement Serializable in the client class using serialVersionUID, how can I make multithreading work with the same server or is there any better way..?
Class 1 - server main
public class EchoServer {
private ServerSocket server;
private int portNum;
public static final int DEFAULT_PORT = 8081;
public EchoServer(int portNum) {
this.portNum = portNum;
}
public void runServer() {
System.out.println("Echo Server started...");
try {
server = new ServerSocket(portNum);
Socket connection = server.accept();
new Thread(new ClientHandler(connection)).run();
} catch(IOException ex) {
System.err.println("Error encountered! Port is likely already in use! Exiting program...");
ex.printStackTrace();
}
}
public static void main(String[] args) {
if (args.length > 0) {
(new EchoServer(Integer.parseInt(args[0]))).runServer();
} else {
(new EchoServer(DEFAULT_PORT)).runServer();
}
}
}
Class 2
public class ClientHandler implements Runnable {
private ObjectOutputStream output;
private ObjectInputStream input;
private String message;
/** Integer to hold the message number. */
private int messagenum;
private Socket connection;
public ClientHandler(Socket connection) {
this.connection = connection;
}
#Override
public void run() {
do{
handleRequest();
} while (true);
}
public void handleRequest() {
try {
output = new ObjectOutputStream(this.connection.getOutputStream());
input = new ObjectInputStream(this.connection.getInputStream());
do {
try {
message = (String) input.readObject();
System.out.println(messagenum +" Output> " +message);
} catch (EOFException | SocketException e) {
message = null;
}
if (message != null) {
output.writeObject(messagenum +" FromServer> " +message);
output.flush();
++messagenum;
}
} while (message != null);
input.close();
output.close();
this.connection.close();
} catch (IOException | ClassNotFoundException ex) {
System.err.println("Error encountered! Exiting program...");
ex.printStackTrace();
}
}
}
Class 3 - client main
public class EchoClient implements Serializable {
private static final long serialVersionUID = 1L;
private Socket connection;
private ObjectOutputStream output;
private transient ObjectInputStream input;
private String message = "";
private static String serverName;
public static final String DEFAULT_SERVER_NAME = "localhost";
private static int portNum;
BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in));
public EchoClient(String serverName, int portNum) {
this.serverName = serverName;
this.portNum = portNum;
}
public synchronized void runClient() {
try {
connection = new Socket(InetAddress.getByName(serverName), portNum);
output = new ObjectOutputStream(connection.getOutputStream());
input = new ObjectInputStream(connection.getInputStream());
do {
System.out.print("Input> ");
message = keyboard.readLine();
if (message != null){
output.writeObject(message);
output.flush();
message = (String) input.readObject();
System.out.println(message);
}
} while (message != null);
input.close();
output.close();
connection.close();
} catch (IOException ioException) {
ioException.printStackTrace();
} catch (ClassNotFoundException exception) {
exception.printStackTrace();
}
}
public static void main(String[] args) {
switch (args.length) {
case 2:
(new EchoClient(args[0], Integer.parseInt(args[1]))).runClient();
break;
case 1:
(new EchoClient(DEFAULT_SERVER_NAME, Integer.parseInt(args[0]))).runClient();
break;
default:
(new EchoClient(DEFAULT_SERVER_NAME, server.EchoServer.DEFAULT_PORT)).runClient();
}
}
}
Call server.accept() in the loop to accept multiple client connections as mentioned in the other answers. Start a new thread with the Thread.start method instead of Thread.run- What's the difference between Thread start() and Runnable run().
volatile boolean isRunning = true;
public void runServer() {
System.out.println("Echo Server started...");
try {
server = new ServerSocket(portNum);
while(isRunning) {
Socket connection = server.accept();
new Thread(new ClientHandler(connection)).start();
}
} catch(IOException ex) {
System.err.println("Error encountered! Port is likely already in use! Exiting program...");
ex.printStackTrace();
}
}
run server needs to wait for connections in a loop otherwise it will connect once and that is it. It needs to close its connections too. Clean up its threads. that's just in server main. I'm pretty sure this is a duplicate. So keep on researching
As said by efekctive, you need your server.accept() in a loop, else it will accept the first client and exit the program. So put these two lines in runServer() in a loop like this:
boolean isRunning = true;
while(isRunning){
Socket connection = server.accept();
new Thread(new ClientHandler(connection)).run();
}

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();
}
}
}
}

Declaring input/output streams from socket preventing program from continuing

Alright, so I've coded what is going to be a simple communication program using a server, really as a test more than anything else, so I know it's missing a lot, but with the following Client class:
public class Client {
private ObjectInputStream in;
private ObjectOutputStream out;
private Socket socket;
private String server;
private int port;
public Client(String ip, int p){
port = p;
server = ip;
}
public boolean start(){
try{
socket = new Socket(server, port);
}catch(Exception e){
System.out.println("Exception");
e.printStackTrace();
return false;
}
try{
in = new ObjectInputStream(socket.getInputStream());
out = new ObjectOutputStream(socket.getOutputStream());
System.out.println("All declared");
}catch(Exception e){
System.out.println("Exception");
e.printStackTrace();
return false;}
new LThread().start();
return true;
}
private void sendMessage(Message msg){
try{
out.writeObject(msg);
}catch(Exception e){}
}
public static void main(String[] args){
int portNum = 1500;
String servers = "localhost";
Client client = new Client(servers, portNum);
System.out.println("Client started");
if(!client.start()){
System.out.println("Didn't work");
return;
}
System.out.println("Client started again");
Scanner scan = new Scanner(System.in);
while(true){
String i = scan.nextLine();
client.sendMessage(new Message(2, i));
}
}
class LThread extends Thread{
public void run(){
System.out.println("Lthread running");
while(true){
try{
String message = (String)in.readObject();
System.out.println(message);
}catch(Exception e){
e.printStackTrace();}
}
}
}
}
The program simply stops when it reaches the point at which it declares its ObjectInput and Output Streams. The program doesn't exit, it doesn't appear to enter the catch block, and I cannot, at all, figure out what on earth could possibly be causing it. The line "All declared." is never printed, but anything before it is printed. Could anyone please tell me why my program just ceases to function at this point without displaying any errors?
EDIT: I figure that there could be an error somewhere in my Server file, so here's the class:
public class Server {
private static int uid;
private ArrayList<ClientThread> clients;
private int port;
private boolean cont;
public Server(int p){
port = p;
clients = new ArrayList<ClientThread>();
}
public void start(){
System.out.println("Started");
cont = true;
try{
ServerSocket srvr = new ServerSocket(port);
System.out.println("Declared socket");
while(cont){
Socket sk = srvr.accept();
System.out.println("Socket accepted");
if(!cont)break;
ClientThread t = new ClientThread(sk);
clients.add(t);
t.start();
}
try{
srvr.close();
for(ClientThread t : clients){
t.in.close();
t.out.close();
t.socket.close();
}
}catch(Exception e){
e.printStackTrace();
}
}catch(Exception e){
e.printStackTrace();
}
}
private synchronized void broadcast(String msg){
for(int i=clients.size(); --i >= 0;){
ClientThread t= clients.get(i);
if(!t.writeMsg(msg)){
clients.remove(i);
}
}
}
public static void main(String[] args){
int portNum = 1500;
Server server = new Server(portNum);
server.start();
}
class ClientThread extends Thread{
Socket socket;
ObjectInputStream in;
ObjectOutputStream out;
String name;
int id;
Message m;
ClientThread(Socket s){
id = ++uid;
socket = s;
try{
System.out.println("Before");
in = new ObjectInputStream(socket.getInputStream());
out = new ObjectOutputStream(socket.getOutputStream());
System.out.println("After");
}catch(Exception e){
e.printStackTrace();}
}
public void run(){
boolean c = true;
while(c){
try{
m = (Message)in.readObject();
switch(m.getType()){
case 2:
broadcast(m.getMessage());
}
}catch (Exception e){
e.printStackTrace();}
}
}
public boolean writeMsg(String msg){
if(!socket.isConnected()){
return false;
}
try{
out.writeObject(msg);
}catch(Exception e){
e.printStackTrace();}
return true;
}
}
}
Alright, another edit. So I added those two printlns to the try statement in ClientThread's constructor, and, just like with client, it runs until I try to initialize the streams, and then it just stops. Again, no errors, no anything; it just completely stops in its tracks. I cannot figure out why on earth this happens, but if it means anything, I'm using the Eclipse IDE to run it.
I snagged on this the first time I used ObjectInputStream and ObjectOutputStream. At the root cause of your problem is within the constructor ObjectInputStream. The constructor will read from the underlying stream in an attempt to get header information such as the wire format version.
In order to prevent your client and server from infinity waiting for the other to send the information first, you should invert the order of the input and output streams, then flush the output stream explicitly. The following at the construction of the streams in the client and server will fix your problem:
out = new ObjectOutputStream(socket.getOutputStream());
out.flush();
in = new ObjectInputStream(socket.getInputStream());

Java Socket not working on LAN [duplicate]

This question already has answers here:
Official reasons for "Software caused connection abort: socket write error"
(14 answers)
Closed 9 years ago.
There are two computers, A and B, each one of them is waiting for the other one to tell him that is ready, when they receive the message they'll start doing something.
public class SyncClientImpl implements SyncClient, Runnable {
private Socket s;
private String ipAddress;
private int port;
private boolean otherIsReady;
private Thread thread;
private OutputStream os;
private ObjectOutputStream oos;
public Thread getThread() {
return thread;
}
public void setThread(Thread thread) {
this.thread = thread;
}
public void start() {
thread = new Thread(this);
thread.start();
}
public boolean isOtherIsReady() {
return otherIsReady;
}
public void setOtherIsReady(boolean otherIsReady) {
this.otherIsReady = otherIsReady;
}
public Socket getS() {
if (s == null) {
try {
s = new Socket(ipAddress, port);
} catch (UnknownHostException ex) {
Logger.getLogger(SyncClientImpl.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(SyncClientImpl.class.getName()).log(Level.SEVERE, null, ex);
}
}
return s;
}
public void setS(Socket s) {
this.s = s;
}
public String getIpAddress() {
return ipAddress;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
#Override
public void send(Object o, int port, String ipAdrress) {
try {
os = this.getS().getOutputStream();
oos = new ObjectOutputStream(os);
oos.flush();
oos.writeObject(o);
oos.flush();
} catch (IOException ex) {
Logger.getLogger(SyncClientImpl.class.getName()).log(Level.SEVERE, null, ex);
}
}
#Override
public void update() {
otherIsReady = true;
}
#Override
public void run() {
try {
while (!otherIsReady) {
try {
this.send("ready", port, ipAddress);
Thread.sleep(500);
} catch (InterruptedException ex) {
Logger.getLogger(SyncClientImpl.class.getName()).log(Level.SEVERE, null, ex);
}
}
oos.close();
os.close();
s.close();
} catch (IOException ex) {
Logger.getLogger(SyncClientImpl.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
This first class sends the message "ready" to a server, it will stop doing it until someone else notify it.
The class that will notify it is this one:
public class SyncServerImpl implements SyncServer, Runnable {
private ServerSocket ss;
private Socket s;
private String ipAddress;
private int port;
private InputStream is;
private ObjectInputStream ois;
private boolean confirmReceived;
private Thread thread;
private transient List<Observer> list = new ArrayList<Observer>();
private Object lock;
public boolean isConfirmReceived() {
return confirmReceived;
}
public void setConfirmReceived(boolean confirmReceived) {
this.confirmReceived = confirmReceived;
}
#Override
public void setLock(Object lock) {
this.lock = lock;
}
public void start() {
thread = new Thread(this);
thread.start();
}
public Socket getS() {
if (s == null) {
try {
s = this.getSS().accept();
} catch (UnknownHostException ex) {
Logger.getLogger(SyncClientImpl.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(SyncClientImpl.class.getName()).log(Level.SEVERE, null, ex);
}
}
return s;
}
public void setS(Socket s) {
this.s = s;
}
public String getIpAddress() {
return ipAddress;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public ServerSocket getSS() {
if (ss == null) {
try {
ss = new ServerSocket(port);
} catch (IOException ex) {
Logger.getLogger(SyncServerImpl.class.getName()).log(Level.SEVERE, null, ex);
}
}
return ss;
}
public void setSS(ServerSocket ss) {
this.ss = ss;
}
#Override
public void addObserver(Observer observer) {
list.add(observer);
}
#Override
public void removeObserver(Observer observer) {
list.remove(observer);
}
#Override
public void notifyObservers() {
for (Observer observer : list) {
observer.update();
}
}
public void receive() {
try {
is = this.getS().getInputStream();
ois = new ObjectInputStream(is);
String to = (String) ois.readObject();
if (to.equalsIgnoreCase("ready")) {
synchronized (lock) {
confirmReceived = true;
this.notifyObservers();
lock.notifyAll();
}
System.out.println("packet received");
}
} catch (IOException ex) {
Logger.getLogger(SyncServerImpl.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(SyncServerImpl.class.getName()).log(Level.SEVERE, null, ex);
}
}
#Override
public void run() {
try {
while (!confirmReceived) {
this.receive();
}
ois.close();
is.close();
s.close();
ss.close();
} catch (Exception ex) {
Logger.getLogger(SyncServerImpl.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void main(String args[]) {
final Object lock = new Object();
SyncServerImpl ss = new SyncServerImpl();
SyncClientImpl sc = new SyncClientImpl();
ss.setLock(lock);
ss.addObserver(sc);
ss.setPort(2002);
ss.start();
sc.setIpAddress("192.168.1.101");
sc.setPort(2002);
sc.start();
synchronized (lock) {
while (!ss.isConfirmReceived()) {
try {
lock.wait();
} catch (InterruptedException ex) {
}
}
}
System.out.println("Ok");
}
}
This Server is waiting for the message "ready" to arrive, when it comes it will notify the other class which will stop sending packets, and will notify the main thread waiting on the lock.
It works fine on the localhost but not on my LAN.
I have a mac and a pc, if I start the main method first from the pc and then from the mac, I get this error (from the mac, which will iterate endlessly).
sync.SyncClientImpl send
GRAVE: null
java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
at java.io.ObjectOutputStream$BlockDataOutputStream.drain(ObjectOutputStream.java:1864)
at java.io.ObjectOutputStream$BlockDataOutputStream.setBlockDataMode(ObjectOutputStream.java:1773)
at java.io.ObjectOutputStream.<init>(ObjectOutputStream.java:229)
at tetris.logic.online.sync.SyncClientImpl.send(SyncClientImpl.java:87)
at tetris.logic.online.sync.SyncClientImpl.run(SyncClientImpl.java:106)
at java.lang.Thread.run(Thread.java:695)
while of the pc it reports me that the connection is refused (but it's ok because it starts first)
If I start first on the mac and the on the pc, I get this error (from the pc) which will iterate endlessly too:
sync.SyncClientImpl send
GRAVE: null
java.net.SocketException: Software caused connection abort: socket write error
...
at tetris.logic.online.sync.SyncClientImpl.send(SyncClientImpl.java:87)
at tetris.logic.online.sync.SyncClientImpl.run(SyncClientImpl.java:106)
at java.lang.Thread.run(Thread.java:695)
This error looks like to be the same of one above but described in a different manner.
Does any one knows what is causing this error?
Try to simplify your solution, and take a look at the following article on socket programming: Writing the Server Side of a Socket.
Try to make it work one way first before attempting to do it in both directions (although the need for that feature isn't quite clear to me). Right now the client & server threads within the same applications are interfering with the client/server pair you're trying to set up over the network.
If you only want to send text over the socket just use BufferedReader and PrintWriter instead of ObjectStreams (latter could get you into memory issues if not managed properly).
#Override
public void send(String line, int port, String ipAdrress) {
try {
Socket clientSocket = new Socket(ipAddress, port);
os = clientSocket.getOutputStream();
PrintWriter out= new PrintWriter(os, true);
out.println(line);
out.close();
clientSocket.close();
} catch (IOException ex) {
Logger.getLogger(SyncClientImpl.class.getName()).log(Level.SEVERE, null, ex);
}
}
If you only want to use the connection for checking if the other is ready than closing the Socket is ok, but if you'd want to keep the connection open you need to keep the OutputStream (not the Socket itself) for further processing in the Thread. Again, take a look at the article above and work from there.

Java thread monitor other threads

I have a class called class1 in which I have the following code:
public class class1 {
public static ServerSocket serverSocket;
public static void main(String args[]) {
try {
serverSocket = new ServerSocket(1234);
while (true) {
class2 t = new class2(serverSocket.accept());
t.start();
}
} catch (IOException ex) {
Logger.getLogger(LisenerServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
So in class 1 I open a new thread for each connection.
And I have another class called class2 in which I have the following code:
public class class2 extends Thread {
private Socket socket;
public class2(Socket socket) {
try {
this.socket = socket;
in = new BufferedInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
} catch (IOException ex) {
Logger.getLogger(ListenerServerThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
#Override
public void run() {
while (true) {
try {
// do something with in and out.
} catch (IOException ex) {
System.out.println(ex);
break;
}
}
}
}
I want clients (not java programs) to connect to my socket server and send sting commands, and I want to know if a client (I will identify the client by the thread name and/or id opened in class 1) is connected or not.
Can I make another class let's say class 3 in which I open a single thread to continuously check if the clients are connected or not? If I can, can you please give me an example?
I hope I got the question right, according to what I understood you could keep a global list of connected clients, for example:
List<class2> MyList;
When the class2 thread starts it adds itself to the list:
public class2(Socket socket) {
try {
this.socket = socket;
in = new BufferedInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
MyList.add(this);
}
catch (IOException ex)
{
Logger.getLogger(ListenerServerThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
When the thread terminates it removes itself from the list:
Try
{
while (true) {
try {
// do something with in and out.
} catch (IOException ex) {
System.out.println(ex);
break;
}
}
}
finally {
for (int i=0; i < MyList.size(), i++)
if (MyList.get(i) == this)
{
MyList.delete(i);
break;
}
}
This way you could have a list of connected clients through its thread. You could add some method in your class2 to access more information, like the socket, the time it has been running, etc, etc. Also, you should consider accessing this list (when adding/deleting) with a mutex or some other synchronization method.

Categories