有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java服务器客户端socket编程

我建立了一个安卓 TCP连接,其中服务器用java编写,客户端用安卓编写。它基本上是一个服务器-客户端聊天。代码很好,运行良好。问题是,当我关闭安卓客户端时,服务器会忘记客户端,不会再次检索该客户端,但服务器和客户端都需要重新启动。我希望当我关闭客户端但服务器仍在运行并再次运行客户端时,服务器应搜索其最近的客户端并恢复服务器客户端聊天。我在提供我的代码。如果有人能尽快帮我修改代码,我将不胜感激。 谢谢

TCPServer。爪哇

import javax.swing.*;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
* The class extends the Thread class so we can receive and send messages at the same   time */
public class TCPServer extends Thread {

public static final int SERVERPORT = 4444;
private boolean running = false;
private PrintWriter mOut;
private OnMessageReceived messageListener;

public static void main(String[] args) {

    //opens the window where the messages will be received and sent
    ServerBoard frame = new ServerBoard();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);

}

/**
 * Constructor of the class
 * @param messageListener listens for the messages
 */
public TCPServer(OnMessageReceived messageListener) {
    this.messageListener = messageListener;
}


/**
 * Method to send the messages from server to client
 * @param message the message sent by the server
 */
public void sendMessage(String message){
    if (mOut != null && !mOut.checkError()) {
        mOut.println(message);
        mOut.flush();
    }
}

@Override
public void run() {
    super.run();

    running = true;

    try {
        System.out.println("S: Connecting...");

  //create a server socket. A server socket waits for requests to come in over network.
        ServerSocket serverSocket = new ServerSocket(SERVERPORT);


        Socket client = serverSocket.accept();
        System.out.println("S: Receiving...");

        try {

            //sends the message to the client
   mOut = new PrintWriter(new BufferedWriter(new    OutputStreamWriter(client.getOutputStream())), true);

            //read the message received from client
            BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));

            //in this while we wait to receive messages from client (it's an infinite loop)
            //this while it's like a listener for messages
            while (running) {
                String message = in.readLine();

                if (message != null && messageListener != null) {
                    //call the method messageReceived from ServerBoard class
                    messageListener.messageReceived(message);
                }
            }

        } catch (Exception e) {
            System.out.println("S: Error");
            e.printStackTrace();
        } finally {
            client.close();
            System.out.println("S: Done.");
        }

    } catch (Exception e) {
        System.out.println("S: Error");
        e.printStackTrace();
    }

}


//Declare the interface. The method messageReceived(String message) will must be implemented in the ServerBoard
//class at on startServer button click
public interface OnMessageReceived {
    public void messageReceived(String message);
} }

共 (2) 个答案

  1. # 1 楼答案

    我认为关键在于如何识别客户机,这样一旦它回来,您就可以期望服务器记住它。我在服务器代码中看不到它跟踪客户机的逻辑

    话虽如此,识别TCP客户端的一种方法是使用客户端的IP地址和端口号。如果我们关闭该TCP客户端并重新启动它,客户端的端口号可能无法保证,因为大多数TCP客户端不调用bind(),而只是使用connect()获取临时端口号。或者,您可以使用应用程序层逻辑(记住,应用程序位于TCP之上),客户机可以使用唯一标识符,也可以要求服务器为其提供唯一标识符。因此,当客户端返回时,它会告诉服务器它有一个标识符,并且希望恢复该连接。这样,服务器就可以将新的fd与之前发布的标识符相关联。请注意,如果服务器发出标识符,则更容易保证标识符的唯一性。例如,服务器可以递增地发出标识符

  2. # 2 楼答案

    我假设某种聊天应用程序——当用户在他/她的Android设备上点击应用程序时——会将最后的消息显示为历史记录

    识别客户的部分是你必须从设计的角度考虑的事情,比如数据隐私。让我来解释几个备选方案:

    • 按地址标识客户机:这是一个可以通过client.getInetAddress().getHostAddress()获得的字符串。由于IP地址可以在DHCP环境中重复使用,并且安卓设备的主机名由安卓定义,用户无法更改,因此这种识别方法可能是一种好方法,但不一定总是同一个客户端。当另一个安卓设备被意外识别并获得另一个用户的历史记录时,你的应用程序会发生什么
    • 您可能希望将设备的IMEI作为唯一标识符传输到服务器,并使用它来标识用户/应用程序。有关如何使用getDeviceId()的信息,请参见TelephonyManager
    • 使用上面的两个标识,您可以标识用户/设备/应用程序,而不让用户知道您这样做了。这可能是一个法律问题,具体取决于你的应用程序环境的敏感程度(例如,公共德语应用程序与私人little helper应用程序)。因此,解决方法是创建用户帐户,让用户注册、登录、使用应用程序并注销。然后,用户可以在注册时签署免责声明。当然,这是迄今为止最复杂的解决方案

    最后,您需要存储消息的历史记录。我会展开messageListener.messageReceived(message);行和sendMessage(String message)方法来保存消息,例如,在每个客户机的文件中