首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >消息只发送给在我的聊天程序中发送消息的客户端。

消息只发送给在我的聊天程序中发送消息的客户端。
EN

Stack Overflow用户
提问于 2017-04-11 04:05:44
回答 1查看 47关注 0票数 0

在我的聊天客户机/服务器程序中,我在向所有连接的客户端广播消息时遇到了困难。发送的消息似乎只被发送回原始服务器,即使我正在迭代一个ArrayList。我有一个套接字的ArrayList和一个将读消息作为参数并为每个套接字创建一个PrintWriter的方法。我认为这个问题与我的客户类有关(如果我错了,请原谅),但我还没有搞清楚是什么。

客户类:

代码语言:javascript
运行
复制
public class H7Client extends Thread implements ActionListener{

private JTextField jtfPortName = new JTextField(20);
private JTextField jtfHostName = new JTextField(20);
private String hostName;
private int portNumber;

private JTextArea jtaChat = new JTextArea("Send a message to the client", 15,40);
private JTextArea jtaRecive = new JTextArea("WELCOME TO THE CHAT!", 15,40);
private JTextField jtfUName = new JTextField("user");



public H7Client(){
    JFrame defaultFrame = new JFrame();

    JLabel jlPortName = new JLabel("Enter The Port number");
    JLabel jlHostName = new JLabel("Enter the Host name");
    JLabel jlUName = new JLabel("Enter a username");

    JButton jbSetSocketInfo = new JButton("Confirm Port and Host Info");
    JButton jbExit = new JButton("Exit");
    JButton jbSendText = new JButton("Send");

    jbSetSocketInfo.addActionListener(this);
    jbExit.addActionListener(this);
    jbSendText.addActionListener(this);



    JPanel jpNorth = new JPanel();
    JPanel jpCenter = new JPanel();
    JPanel jpLabels = new JPanel();

    defaultFrame.add(jpNorth,BorderLayout.NORTH);
    jpNorth.add(jbSetSocketInfo,BorderLayout.EAST);
    jpNorth.add(jbSendText, BorderLayout.CENTER);
    jpNorth.add(jbExit,BorderLayout.WEST);


    defaultFrame.add(jpCenter,BorderLayout.CENTER);
    jpCenter.add(jtaChat,BorderLayout.SOUTH);
    jpCenter.add(jpLabels,BorderLayout.NORTH);

    jpLabels.setLayout(new GridLayout(2,3));
    jpLabels.add(jlHostName);
    jpLabels.add(jlPortName);
    jpLabels.add(jlUName);
    jpLabels.add(jtfHostName);
    jpLabels.add(jtfPortName);
    jpLabels.add(jtfUName);

    defaultFrame.add(jtaRecive,BorderLayout.SOUTH);

    defaultFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);


    defaultFrame.setLocationRelativeTo(null);
    defaultFrame.setSize(800,800);
    defaultFrame.setVisible(true);

}

public void setClientComms(String message){
    try{
        // open communications to the server
        Socket s = new Socket(hostName, portNumber);
        ClientThread ct = new ClientThread(s, message);
    }
    catch(IOException e){
        e.printStackTrace();
    }
}

class ClientThread extends Thread{

    public ClientThread(Socket sock, String msg) {

        try {

            // open input stream
            InputStream in = sock.getInputStream();
            BufferedReader br = new BufferedReader(
                    new InputStreamReader(in));

            // open output stream
            OutputStream out = sock.getOutputStream();
            PrintWriter pout = new PrintWriter(
                    new OutputStreamWriter(out));


            // write something to the server
            pout.println(msg);

            // make sure it went
            pout.flush();

            // read something back from server
            String incomingMessage = br.readLine();

            // print the something to the user
            System.out.println("Message: " + msg);
            //jtaChat.setText("");
            jtaRecive.append("\n" + msg);


            // Send the terminating string to the server
            pout.println("quit");
            pout.flush();

            // close everything
            pout.close();
            br.close();
            sock.close();
        } catch (UnknownHostException uhe) {
            System.out.println("What host you speak of?");
        } catch (IOException ioe) {
            System.out.println("Bad IO?");
            ioe.printStackTrace();
        }
    }
}

public void actionPerformed(ActionEvent event) {
    if (event.getActionCommand().equals("Exit")) {
        System.exit(0);
    } else if (event.getActionCommand().equals("Send")) {
        String chatMessage = jtaChat.getText();
        jtaChat.setText("");
        setClientComms(chatMessage);


    } else if (event.getActionCommand().equals("Confirm Port and Host Info")) {
        hostName = jtfHostName.getText();
        //NEED TO ADD IN WAY TO HANDLE IP ADDRESSES
        portNumber = Integer.parseInt(jtfPortName.getText());
    }
}


public static void main(String [] args) {

    new H7Client();


}

}

服务器类:

代码语言:javascript
运行
复制
public class H7Server{

public ArrayList<Socket> clients = new ArrayList<Socket>();

public static void main(String[] args){new H7Server();}
public H7Server()
{



    ServerSocket ss = null;

    try {
        System.out.println("getLocalHost: "+ InetAddress.getLocalHost() );
        System.out.println("getByName:    "+InetAddress.getByName("localhost") );

        ss = new ServerSocket(16789);
        Socket cs = null;
        while(true){        // run forever once up
            //try{
            cs = ss.accept();               // wait for connection
            clients.add(cs);
            ThreadServer ths = new ThreadServer( cs );
            ths.start();
       } // end while
    }
    catch( BindException be ) {
        System.out.println("Server already running on this computer, stopping.");
    }
    catch( IOException ioe ) {
        System.out.println("IO Error");
        ioe.printStackTrace();
    }

} // end main

class ThreadServer extends Thread {
    Socket cs;

    public ThreadServer( Socket cs ) {
        this.cs = cs;
    }

    public void run() {

           BufferedReader br;
           String clientMsg;
           try {
               br = new BufferedReader(
                       new InputStreamReader(
                               cs.getInputStream()));


               clientMsg = br.readLine();                // from client
               System.out.println("Server read: " + clientMsg);
               while(clientMsg != null) {
                   sendMessage(clientMsg);
               }

           } catch (IOException e) {
               System.out.println("Inside catch");
               e.printStackTrace();
           }


    }

    public synchronized void sendMessage(String s){
        try{
            for(Socket sock: clients) {
                PrintWriter pw = new PrintWriter(new OutputStreamWriter(sock.getOutputStream()));

                pw.println(s);
                pw.flush();
            }
        }
        catch(IOException e){
            e.printStackTrace();
        }


    }

} // end class ThreadServer

}

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-04-11 06:03:25

正如您所怀疑的,客户机类和服务器类都存在问题。有两件事你需要解决。

首先,您从服务器接收消息,但没有对它做任何操作。客户端在ClientThread构造函数的try块中接收到ClientThread,但未使用。一个可能的修复方法是将其附加到jtaReceive中,并删除另一个附加部分,但不要这样做。

为了进行实时聊天,客户端必须至少有两个线程:一个用于发送消息,另一个用于不断检查是否有任何消息要接收。也许,这正是您试图通过ClientThread实现的,但不幸的是,它并不起作用。除了错误的代码之外,使用ClientThread还会创建一个Thread,但不会实际运行它。您需要在run方法中有一个线程,该线程包含一个永久的while循环,该循环不断地接收来自服务器的消息。一个实现是这样的:(您可以重命名为任何您喜欢的)

代码语言:javascript
运行
复制
class ReceiverThread extends Thread {

    private BufferedReader s;

    public ReceiverThread(Socket sock) throws IOException {
        s = new BufferedReader(new InputStreamReader(sock.getInputStream()));
    }

    @Override
    public void run() {
        while (true) 
            try {
                String message = s.readLine();
                // ...code to do whatever with message...
            } catch (IOException e) {
                e.printStackTrace();
            }
    }

}

此外,您还需要创建一个保持打开状态的套接字(在确认主机和端口信息时,可以使用套接字创建并启动这个线程)。

服务器类的问题是我们所有人都要面对的问题:臭名昭著的ConcurrentModificationException。您可以阅读有关它的这里,但基本上这个异常是在修改(添加、删除等)时抛出的。当你不应该这样做的时候,数据结构。所讨论的数据结构是ArrayList of Socket's,以及在发送消息时for-each循环中的时间。基本上,在运行该循环时,创建while‘s的while循环将它们添加到ArrayList中并抛出异常。要解决这个问题,您需要在处于ArrayList循环中时停止修改for,可能是通过移除while循环、在for循环完成之前保持while循环,或者甚至在for循环处于活动状态时添加一个由套接字组成的Queue,但是有很多方法可以做到这一点。

我假设您的服务器只接收一条消息,只是为了测试,但是如果您决定能够聊天多条消息,则必须使用用于客户端类的额外线程。

祝你好运:)

注意:我建议不要使用AWT thread (调用actionPerformed的线程)来建立网络/任何可能需要时间的东西,否则应用程序GUI实际上就会冻结。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43336575

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档