[英]Java: Multiple Thread Chat Server Sends message to only 1 client
在我之前的问题中获得很多帮助之后,我终于尝试建立多个客户。 它无法正常工作,在发布整个代码之前,我将尝试解释代码的基本知识。
基本课程:
ChatServer.Java-启动ServerSocket。 等待用户连接。 将用户添加到ArrayList。 为每个用户启动一个新线程。 它启动的线程将等待来自客户端的输入,并遍历客户端列表,并将消息发送给所有人。
CharServer2.Java:仅一个GUI界面即可启动聊天服务器
聊天1:连接到套接字。 发送和接收消息。 两种动作都在不同的线程上。
ChatClient.Java:Chat1触发器的GUI。
现在,如果我启动服务器并连接一个客户端,则可以正常工作。 如果我添加两个客户,事情会变得很糟:(。
可以说我添加了User1和User2。 User1发送消息:ConcurrentModificationException User2发送消息:无异常。 该代码在Arraylist中循环。 查找两个套接字,并尝试向两个套接字发送消息。 但是邮件仅到达用户1
我在代码中遇到的另一个问题是,每当我关闭任何一个用户ChatServer上的窗口时,都会抛出套接字已关闭的异常。 请注意,所有这一切都在我的本地计算机上发生。 但是,两个用户都占用不同的端口。
这是完整的代码:
聊天服务器
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<Socket> 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<Socket>();
}
@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<Socket> clientList;
private Socket currentClient;
private BufferedReader reader;
private PrintWriter writer;
String msg;
public transmitMessagestoAll(Socket curr){
clientList = new ArrayList<Socket>();
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;
}
}
}
}
聊天1.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");
}
}
}
我在代码中找到了错误。 当代码向所有客户端推送消息时,有一个readLine方法调用有效地擦除了文本,因此将空白行推送至第二个客户端和其他客户端。 这样,并发修改的问题也消失了。 我可以将整个代码发布给可能正在从事类似工作的任何人。 只需添加评论,我将其发布..
代码更正:类ChatServer
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.