【问题标题】:Clients can't communicate with each other客户端无法相互通信
【发布时间】:2017-04-18 12:45:52
【问题描述】:

我编写了一个让多个用户聊天的聊天程序。问题是客户端无法看到其他客户端键入的内容。服务器运行良好,它接受多个客户端及其输入。我创建了一个ArrayList 来将客户端列表存储在我的服务器中,以便他们查看其他客户端键入的内容,但它似乎不起作用。

这是我的代码

服务器

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
    public class myServerSocket {

        int portNumber = 4434;
        ServerSocket serverSocket = null;
        Socket clientSocket;
        ArrayList<myServerSocketRunnable> clients = new ArrayList<myServerSocketRunnable>();

        public void runServer() {
            try {
                while(true) {
                    serverSocket = new ServerSocket(portNumber);
                }
            } catch(IOException aww) {
                System.out.println(aww.getMessage());
                aww.printStackTrace();
            }

            try {
                while(true) {
                    clientSocket = serverSocket.accept();
                    myServerSocketRunnable client = new myServerSocketRunnable(clientSocket);
                    clients.add(client);
                    new Thread(new myServerSocketRunnable(clientSocket)).start();
                }
            } catch(IOException aww) {
                System.out.println(aww.getMessage()+"\n");
            } finally {
                try {
                    clientSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

    }



import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class myServerSocketRunnable extends Thread {

    protected Socket clientSocket = null;
    BufferedReader in;
    PrintWriter out;
    String username; 
    String message;

    public myServerSocketRunnable(Socket clientSocket) {
        this.clientSocket = clientSocket;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        try {
            while(true) {
                in =  new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                out = new PrintWriter(clientSocket.getOutputStream(), true);

                username = in.readLine();
                message = in.readLine();

                System.out.println(" "+username+": "+message);
                out.println(" "+username+": "+message);
                out.flush();
            }
        } catch(IOException aww) {
            System.out.println(" "+username+" has disconnected!");
            out.println(" "+username+" has disconnected!"); 
        } finally {
            try {
                in.close();
                out.close();
            } catch(IOException aww) {
                aww.printStackTrace();
            }
        }
    }

}




public class myServer {

    public static void main(String[] args) {

        myServerSocket call = new myServerSocket();

        System.out.println("=========================================");
        System.out.println("=             Messenger Server          =");
        System.out.println("=========================================");

        call.runServer();
    }
}

客户

import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JButton;
import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
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.Socket;


public class Messenger {
    private static String hostName = "127.0.0.1";
    private static int portNumber = 4434;
    private static Socket clientSocket;
    private static PrintWriter out;
    private static BufferedReader in;

    private static String username, content;
    private static JFrame firstFrame, secondFrame;
    private static JTextField userName, userField, clientTextField;
    private static JTextArea clientTexts;
    private static JButton talkButton, sendButton;


    public static void firstGUI(Container pane) {
        pane.setLayout(null);

        userName = new JTextField("Username :");
        userName.setBounds(10, 35, 70, 20);
        userName.setEditable(false);

        userField = new JTextField();
        userField.setBounds(10, 55, 225, 20);

        talkButton = new JButton("Talk!");
        talkButton.setBounds(85, 100, 70, 35);
        talkButton.setFont(new Font("Verdana", Font.PLAIN, 15));

        pane.add(userName);
        pane.add(userField);
        pane.add(talkButton);
        pane.setBackground(Color.DARK_GRAY);

        talkButton.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                username = userField.getText();
                showFrame();
                talkButton.setEnabled(false);
                firstFrame.dispose();
            }
        });

    }

    public static void showGUI() {

        firstFrame = new JFrame("Messenger");
        firstFrame.setVisible(true);
        firstFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        firstFrame.setBounds(500, 100, 250, 200);
        firstFrame.setResizable(false);

        firstGUI(firstFrame.getContentPane());
    }

    public static void contentGUI(Container pane) {

        pane.setLayout(null);

        clientTexts = new JTextArea();
        clientTexts.setEditable(false);
        clientTexts.setBounds(15, 10, 465, 490);
        clientTexts.setBackground(Color.WHITE);
        clientTexts.setFont(new Font("Verdana", Font.PLAIN, 13));

        clientTextField = new JTextField();
        clientTextField.setText("");
        clientTextField.setBounds(15, 525, 360, 25);
        clientTextField.setBackground(Color.WHITE);
        clientTextField.setFont(new Font("Verdana", Font.PLAIN, 15));

        sendButton = new JButton("Send");
        sendButton.setBounds(405, 519, 75, 35);
        sendButton.setFont(new Font("Verdana", Font.PLAIN, 15));

        pane.add(clientTexts);
        pane.add(clientTextField);
        pane.add(sendButton);
        pane.setBackground(Color.DARK_GRAY);

        sendButton.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                content = clientTextField.getText();
                clientTextField.setText("");
                new Thread(new Runnable() {
                    public void run() {
                        try {
                            out.println(username);
                            out.println(content);
                            out.flush();
                            clientTexts.append(in.readLine()+"\n");
                        } catch (IOException aww) {
                            aww.printStackTrace();
                        }
                    }
                }).start();

            }
        });
    }

    public static void showFrame() {

        secondFrame = new JFrame("Messenger - Client");
        secondFrame.setVisible(true);
        secondFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        contentGUI(secondFrame.getContentPane());

        secondFrame.setBounds(550, 100, 500, 600);
        secondFrame.setResizable(false);


    }

    public static void main(String[] args) {

        try {
            showGUI();
            clientSocket = new Socket(hostName, portNumber);
            out = new PrintWriter(clientSocket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        } catch(IOException aww) {
            userField.setForeground(Color.RED);
            userField.setFont(new Font("Courier new", Font.PLAIN, 13));
            userField.setText("Server is not Online");
            userField.setEditable(false);
            talkButton.setEnabled(false);

            aww.printStackTrace();
        }

    }

}

我想知道代码的哪一部分是错误的。也许是解决问题的解决方案。

【问题讨论】:

  • "... but it doesn't seem to be working" -- 是我们能够帮助回答的难题。可能是时候使用调试器、记录器或两者的组合来首先识别并隔离错误了。
  • 将来,您应该将代码分解成小的、可测试的组件。这样就很容易找出哪些部分有效,哪些部分无效。这里每个班级的职责太多了,我们很难找出哪一部分是错的。
  • 为什么会这样:serverSocket = new ServerSocket(portNumber);while (true) 块内?不应该只调用一次吗?
  • @HovercraftFullOfEels 我明白了。我以为把它放在while 允许多个客户端进入服务器
  • @mahurt:但这不是客户进入的地方,是吗?他们在它下面的适当的while循环中输入,对吧?

标签: java multithreading sockets server client


【解决方案1】:

这里有一个问题:

clientSocket = serverSocket.accept();
myServerSocketRunnable client = new myServerSocketRunnable(clientSocket);
clients.add(client);
new Thread(new myServerSocketRunnable(clientSocket)).start();

您正在创建 两个 myServerSocketRunnable 对象,一个添加到客户端列表中,另一个放置在线程中并运行,这可能是一个严重的问题。而是为两者创建一个:

clientSocket = serverSocket.accept();
myServerSocketRunnable client = new myServerSocketRunnable(clientSocket);
clients.add(client);

// new Thread(new myServerSocketRunnable(clientSocket)).start(); // NO
new Thread(client).start();     // YES

我不知道这是否是您的问题的原因,但我知道这是不对的,需要修复。另外,正如我在 cmets 中所说,这个 while (true) 循环不属于:

while(true) {
    serverSocket = new ServerSocket(portNumber);
}

只需创建一次您的服务器套接字,然后继续。


另外,您的服务器在哪里将从一个客户端接收到的数据广播到所有其他客户端?我会假设你会为此使用你的客户 ArrayList,但我没有看到它被使用。客户端不能神奇地相互连接,服务器必须提供粘合剂。

【讨论】:

  • 您指的是myServerSocketRunnable client = new myServerSocketRunnable(clientSocket); clients.add(client); 吗?这段代码是我将客户列表存储到ArrayList
  • @mahurt:我已经向您展示了我所指的代码。我知道这是您将客户端放入 ArrayList 的地方,但是您再次创建了两个不必要的 myServerSocketRunnable 对象。但更重要的是——你说你的客户没有交流——哪里有代码可以让他们交流?
  • out.println(" "+username+": "+message); 我猜?
  • 所以我需要创建这个服务器广播数据。谢谢顺便说一句
  • out.println(...) 看起来只向与其绑定的一个客户端发送文本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-03
  • 2023-03-08
  • 2021-07-22
  • 1970-01-01
相关资源
最近更新 更多