2014-07-02 72 views
0

得到了很多的帮助,在我以前的问题,最后我尝试做多客户端后。它不能正常工作,我会尝试在发布整个代码之前解释代码的基础知识。的Java:多线程聊天服务器发送消息到只有1客户

基本类:

ChatServer.Java -启动一个ServerSocket。等待用户连接。将用户添加到ArrayList。为每个用户启动一个新线程。它启动的线程将等待来自客户端的输入并遍历客户端列表并将消息发送给所有客户端。

CharServer2.Java:只是一个GUI界面来启动聊天服务器

客服1:连接到插座上。发送和接收消息。这两个行动在不同的线程。

ChatClient.Java: GUI的客服1触发。

现在,如果我启动服务器,并连接一个客户端能正常工作。如果我添加两个用户事情变得粗糙:(

可以说,我加入用户1和用户 用户1发送消息:。ConcurrentModificationException的 用户2发送消息:没有异常的代码回路在ArrayList中同时找到插座和尝试。发送消息到两个但消息只达到用户1

我在代码中的另一个问题是,每当我关闭任何一个用户ChatServer的窗口抛出异常,套接字已关闭请注意,所有这一切发生在我的本地机器上,两个用户都占用不同的端口,但是

这里是整个代码:

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<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; 


       } 

      } 



     } 


    } 

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"); 

     } 
    } 

} 
+2

为了更好地帮助越早,张贴[MCTaRE](http://stackoverflow.com/help/mcve)(最小完备测试和实施例可读) – Sanjeev

+0

@Sanjeev亦称TL;道歉 –

+0

博士。已经削减了代码。看看这是否容易理解。 – NewGuyInJava

回答

0

我发现的bug的代码。虽然代码向所有客户端推送消息,但是有一个readLine方法调用可以有效地消除文本,以便将空行插入到第二个客户和其他客户端。与此同时修复与并发修改的问题也消失了。我可以发布整个代码给任何可能在类似工作中工作的人。只需添加评论,我将它张贴..

码校正: 类的ChatServer

  • 内部类:transmitMessagestoAll
  • 方法运行,客户端列表上的内循环的ReadLine呼叫被转移到外循环。
+0

请发表评论: – user2883071

相关问题