After getting a lot of help in my previous questions finally I attempted to make a multiple client. Its not working properly and I will try to explain the basics of code before posting whole code.
Basic Classes:
ChatServer.Java -- Starts a ServerSocket. Waits for user to connect. Adds user to ArrayList. Starts a new thread for every user. The thread it starts will wait for inputs to come in from client and loop over list of clients and send the message to all.
CharServer2.Java : Just a GUI interface to start up Chat Server
Chat1: Connects to socket. send and receives messages. Both actions on different threads.
ChatClient.Java : GUI for Chat1 trigger.
Now if I start the server and connect one client it works fine. If I add two clients things get rough :( .
Lets say I added User1 and User2.
User1 send message: ConcurrentModificationException
User2 sends message : No exception. The code loops at Arraylist. Finds both sockets and tries to send message to both. But the message reaches only User 1
Another issue I have in code is that whenever I close window on any one of the users ChatServer throws exception that the socket was closed. Please note that all this is happening my local machine. Both users occupy different ports though.
Here is the whole code:
ChatServer.Java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
public class ChatServer implements Runnable {
private static int port;
private static String ip_add;
private Socket socket;
private ArrayList clients;
private ServerSocket ss;
public ChatServer(String ip_add_in, int port_in) {
// TODO Auto-generated constructor stub
port = port_in;
ip_add = ip_add_in;
clients = new ArrayList();
}
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("ChatServer Start!!" + new Date() );
try {
ss = new ServerSocket(port, 10);
while(true){
socket = ss.accept();
System.out.println("ChatServer Accepts!!" + new Date() );
clients.add(socket);
sendWelcomeMessage();
Thread transmit = new Thread(new transmitMessagestoAll(socket));
transmit.setName("" + socket.getPort());
transmit.start();
// (new Thread(new cleanUp(clients))).start();
if(clients.isEmpty()) {
System.out.println("All users Gone");
break;
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void sendWelcomeMessage() {
// send message via writer
}
public class transmitMessagestoAll implements Runnable {
private ArrayList clientList;
private Socket currentClient;
private BufferedReader reader;
private PrintWriter writer;
String msg;
public transmitMessagestoAll(Socket curr){
clientList = new ArrayList();
clientList = clients;
currentClient = curr;
}
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getName());
while(!clientList.isEmpty()){
System.out.println(clientList.size());
try {
reader = new BufferedReader(new InputStreamReader(currentClient.getInputStream()));
msg = reader.readLine();
while(msg!=null){
for (Socket thisClient : clientList) {
System.out.println(Thread.currentThread().getName()
+ ">>>>>"
+ thisClient.getPort());
writer = new PrintWriter(thisClient.getOutputStream());
System.out.println("Transmitting");
writer.println(msg);
writer.flush();
msg = reader.readLine();
}
System.out.println("-----------------");
}
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("All users Gone! Breaking");
e.printStackTrace();
break;
}
}
}
}
Chat1.Java
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.*;
import javax.swing.*;
import javax.xml.ws.handler.MessageContext.Scope;
public class Chat1 {
JFrame frame;
JPanel msg_pan, chat_pan,connect_pan;
JButton send,connect;
JTextField server_ip;
JTextArea type_area, chat_area;
private static String user;
private SendMsg send_action = new SendMsg();
private Connect connect_action = new Connect();
private Socket writerSocket;
// private Socket readerSocket;
static String ip_address;
static int port;
private PrintWriter writer;
private ReaderThread readerRunner;
private SenderThread senderRunner;
Thread senderThread;
Thread readerThread;
public Chat1(String name, String ip_add_in, int port_in){
user = name;
ip_address = ip_add_in;
port = port_in;
}
public void create_window() {
// GUI and add action Listeners
}
class SendMsg implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
String msg = type_area.getText();
if (msg != null && msg != "") {
msg = user + " :: " + msg ;
senderRunner = new SenderThread(msg);
type_area.setText(null);
senderThread = new Thread(senderRunner);
senderThread.start();
}
}
}
public void startchat(){
create_window();
// System.out.println("Window Done");
connect_socket();
}
public void connect_socket(){
try {
System.out.println("Start Chat" + new Date());
System.out.println(ip_address);
System.out.println(port);
writerSocket = new Socket(ip_address,port);
if(writerSocket.isBound())
{
readerRunner = new ReaderThread();
readerThread = new Thread(readerRunner);
readerThread.start();
System.out.println("Thread Started");
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public class ReaderThread implements Runnable {
InputStreamReader streamReader;
BufferedReader reader;
String msg;
public void run(){
try {
System.out.println("Entered ReaderThread Run");
streamReader = new InputStreamReader(writerSocket.getInputStream());
reader = new BufferedReader(streamReader);
while (true) {
msg = reader.readLine();
if (msg != null) {
msg = msg + "\n";
chat_area.append(msg);
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Leaving ReaderThread Run");
}
}
public class SenderThread implements Runnable{
String msg;
public SenderThread(String msg_in){
msg = msg_in + "\n";
}
public void run(){
System.out.println("Entered SenderThread Run" + msg);
try {
if (writer == null) {
writer = new PrintWriter(writerSocket.getOutputStream());
}
System.out.println("Writer has Error-->" + writer.checkError());
writer.println(msg);
writer.flush();
// writer.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
System.out.println("Sender Thread Run Exception 1");
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("Sender Thread Run Exception 2");
e.printStackTrace();
}
System.out.println("Leaving SenderThread Run");
}
}
}
解决方案
I found the bug in the code. While the code was pushing out messages to all clients there was a readLine method call which effectively wiped out the text so it was pushing blank lines to second and other clients. with that fix the issue with concurrentmodification also went away. I can post the whole code for anyone who might be working on similar lines. Just add a comment and I will post it..
Code Correction:
Class ChatServer
Inner class : transmitMessagestoAll
Method Run, inside the loop on clientList the call to readLine was moved to outside the loop.