【问题标题】:Chat Program: Client to Server Connectivity Issue聊天程序:客户端到服务器连接问题
【发布时间】:2020-03-25 13:50:06
【问题描述】:

项目总结

  • 目标:一个简单的应用程序,将客户端连接到一台计算机上托管的服务器,并允许该客户端从另一台计算机向指定服务器上的每个人发送聊天消息。

  • 类 ClientWindow:运行提示用户输入服务器 ID 和端口的应用程序。输入后,它会启动聊天程序。

问题:

出于某种我不知道的原因,聊天程序仅在连接到您在自己的计算机上创建的服务器时才有效。来自其他计算机的其他客户端无法连接到该服务器。

问题的可能原因:

  • 我可能错误地构造了服务器的接收/发送套接字
  • 我可能错误地构造了客户端的接收/发送套接字
  • 客户端和服务器之间发送的数据包出现问题
  • 不知何故,套接字的 IP 地址定义不正确

这是聊天程序的代码。

启动服务器

此类在指定端口上启动服务器。 (本例中为 12348)

package server;

public class ChatServer {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        Server.start(12348);

        
    }

}

服务器

这是创建服务器并侦听客户端连接和消息的类。

package server;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.ArrayList;

public class Server {

    private static DatagramSocket socket;
    private static boolean running;

    private static int ClientID; // Ensures that no two users have the same client ID
    private static ArrayList<ClientInfo> clients = new ArrayList<ClientInfo>();

    public static void start(int port) {

        try {

            socket = new DatagramSocket(port);
            System.out.println("Application Starting...");
            running = true;
            listen();
            System.out.println("Server started on port: " + port);

        } catch (Exception e) {
            System.out.println("Failed somewhere");
            e.printStackTrace();
        }

    }

    private static void broadcast(String message) {

        for (ClientInfo info : clients) {
            send(message, info.getAddress(), info.getPort());
        }

    }

    private static void send(String message, InetAddress address, int port) {

        try {

            message += "\\e";
            byte[] data = message.getBytes();
            DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
            socket.send(packet);
            System.out.println("Sent message to," + address.getHostAddress() + ":" + port);

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private static void listen() {
        
        Thread listenThread = new Thread("ChatProgram Listener Thread") {
            
            public void run() {
            
                try {
                     while(running) {
                         
                         byte[] data = new byte[1024];
                         DatagramPacket packet = new DatagramPacket(data, data.length); 
                         socket.receive(packet);
                         
                         String message = new String(data);
                         //Identify where the end of the message is
                         message = message.substring(0, message.indexOf("\\e"));
                         
                         //Manage message
                         if(!isCommand(message, packet)) {
                            broadcast(message);
                         }
                        
                     }
                    
                } catch(Exception e){
                    e.printStackTrace();
                }
            }
            
        }; listenThread.start();
        
    }

    /*
     * SERVER COMMAND LIST 
     * \con:[name] -> Connects client to server 
     * \dis:[id] -> Disconnects client from server
     * 
     * 
     * 
     */

    private static boolean isCommand(String message, DatagramPacket packet) {

        if (message.startsWith("\\con:")) {
            // RUN CONNECTION CODE

            String name = message.substring(message.indexOf(":") + 1);
            clients.add(new ClientInfo(name, ClientID++, packet.getAddress(), packet.getPort()));
            broadcast("User " + name + " Connected!");

            return true;
        }

        if (message.startsWith("\\dis:")) {
            // RUN DISCONNECTION CODE
            
            return true;
        }

        return false;
    }

    public static void stop() {

        running = false;

    }
}

启动客户端

启动客户端应用程序。

package client;

import java.awt.EventQueue;
import java.awt.Frame;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextField;
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.awt.event.ActionEvent;

public class ClientWindow {

    private JFrame frmChatProgram;
    private JTextField textField;
    private static JTextArea textArea = new JTextArea();
    private Client client;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {

                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    ClientWindow window = new ClientWindow();
                    window.frmChatProgram.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    
    public ClientWindow() throws UnknownHostException {
        initialize();
        String name = JOptionPane.showInputDialog("Enter name:");
        String servIp = JOptionPane.showInputDialog("Enter server IP address:");
        String port = JOptionPane.showInputDialog("Enter server port:");
        
        int parsedPort = Integer.parseInt(port);
        
        //InetAddress inetAddress = InetAddress.getLocalHost();
        
        client = new Client(name, servIp, parsedPort);
    }

    private void initialize() {
        
        
        frmChatProgram = new JFrame();
        frmChatProgram.setResizable(false);
        frmChatProgram.setTitle("Chat Program");
        frmChatProgram.setBounds(100, 100, 620, 446);
        frmChatProgram.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frmChatProgram.setBackground(Color.WHITE);
        frmChatProgram.getContentPane().setBackground(Color.DARK_GRAY);
        frmChatProgram.getContentPane().setLayout(new BorderLayout(0, 0));
        textArea.setForeground(Color.WHITE);
        
        
        textArea.setBackground(Color.DARK_GRAY);
        JScrollPane scrollPane = new JScrollPane(textArea);
        frmChatProgram.getContentPane().add(scrollPane, BorderLayout.CENTER);
        
        JPanel panel = new JPanel();
        panel.setBackground(Color.GRAY);
        frmChatProgram.getContentPane().add(panel, BorderLayout.SOUTH);
        panel.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
        
        textField = new JTextField();
        textField.setBackground(Color.WHITE);
        panel.add(textField);
        textField.setColumns(40);
        
        JButton btnNewButton = new JButton("Send");
        btnNewButton.addActionListener(e ->{
            
            if (!textField.getText().equals("")) {
                
                client.send(textField.getText());
                textField.setText("");
                
            }
            
            
        });
        panel.add(btnNewButton);
        
        frmChatProgram.setLocationRelativeTo(null);
        
    }
    
    public static void printToConsole(String message) {
        
        textArea.setText(textArea.getText() + message + "\n");
        
    }

}

客户

为该客户端创建客户端连接和侦听器


import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;

import server.ClientInfo;

public class Client {

    private DatagramSocket socket;
    private InetAddress address;
    private int port;
    private boolean running;
    private String name;
    
    public Client(String name, String address, int port) {
        try {
            this.name = name;
            this.address = InetAddress.getByName(address);
            this.port = port;
            socket = new DatagramSocket();
            socket.connect(this.address, port);
            
            running = true;
            listen();
            send("\\con:" + name);

            
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public void send(String message) {

        try {
            
            if (!message.startsWith("\\")) {
            message = name+": "+message;
                
                
            }

            message += "\\e";
            byte[] data = message.getBytes();
            DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
            socket.send(packet);
            System.out.println("Sent message to," + address.getHostAddress() + ":" + port);

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private void listen() {

        Thread listenThread = new Thread("ChatProgram Listener Thread") {

            public void run() {

                try {
                    while (running) {

                        byte[] data = new byte[1024];
                        DatagramPacket packet = new DatagramPacket(data, data.length);
                        socket.receive(packet);

                        String message = new String(data);
                        // Identify where the end of the message is
                        message = message.substring(0, message.indexOf("\\e"));

                        // Manage message
                        if (!isCommand(message, packet)) {
                            
                            ClientWindow.printToConsole(message);
                            
                        }

                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        }; listenThread.start();

    }

    private static boolean isCommand(String message, DatagramPacket packet) {

        if (message.startsWith("\\con:")) {
            // RUN CONNECTION CODE

            return true;
        }

        if (message.startsWith("\\dis:")) {
            // RUN DISCONNECTION CODE

            return true;
        }

        return false;
    }
    
    
    

}

【问题讨论】:

    标签: java sockets networking serversocket packet


    【解决方案1】:

    我假设您是在询问您的代码无法正常工作的可能原因:

    1) 我可能错误地构造了服务器的接收/发送套接字。

    这是可能的。您应该能够通过使用调试器检查服务器端的数据包来判断这一点。

    2) 我可能错误地构造了客户端的接收/发送套接字

    同上...

    3) 客户端和服务器之间发送的数据包出现问题

    这是最有可能的:

    • 这可能是数据包级别的路由问题......尽管这可能会产生更广泛的影响。
    • 可能是防火墙问题
    • 可能是 MTU 问题
    • 甚至可能是开关损坏等。

    4) 不知何故,套接字的 IP 地址定义不正确

    这是可能的。


    您可以采取多种措施来诊断/消除各种可能性。但这并不是真正的 StackOverflow 问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-17
      • 1970-01-01
      • 1970-01-01
      • 2014-04-18
      • 2016-11-07
      • 1970-01-01
      相关资源
      最近更新 更多