简体   繁体   English

服务器客户端套接字编程

[英]Server Client Socket Programming

I have established an android TCP connection in which server is written in java and client is written in android. 我已经建立了一个android TCP连接,其中服务器是用java编写的,而客户端是用android编写的。 It is basically a server client chat. 它基本上是服务器客户端聊天。 The code is all fine and it runs well. 该代码很好,并且运行良好。 The problem is that when I close the android client then the server forgets the client and does not retrieve that client again but the server and client both are needed to start again.I want that when I close the client but the server is still running and run the client again, then server should search his recent client and resume the server client chat. 问题是当我关闭android客户端时,服务器会忘记该客户端并且不会再次检索该客户端,但是服务器和客户端都需要再次启动。我希望在我关闭客户端但服务器仍在运行并且再次运行客户端,然后服务器应搜索其最近的客户端并恢复服务器客户端聊天。 I'm providing my code. 我正在提供我的代码。 Kindly if some one help to modify my code as soon as possible. 如果有人帮助尽快修改我的代码,请。 Thanks 谢谢

TCPServer.java TCPServer.java

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

I think the key is how do you identify a client, so that once it comes back, you expect hte server to remember it. 我认为关键是如何识别客户端,以便一旦它回来,您就希望服务器记住它。 I dont see the logic in the server code where it keeps track of the client. 我看不到服务器代码中跟踪客户端的逻辑。

Having said that, one way to identify the TCP client is to use the IP address and port number of the client. 话虽如此,一种识别TCP客户端的方法是使用客户端的IP地址和端口号。 If we close that TCP client and restart it again, the port number of the client may not be guaranteed since most of hte TCP clients do not call bind() and simply use connect() to get an ephemeral port number. 如果我们关闭该TCP客户端并重新启动,则可能无法保证该客户端的端口号,因为大多数TCP客户端都不调用bind(),而只是使用connect()来获取临时端口号。 Or, you could use an application layer logic (remember the application sits on top of TCP), where the client can use a unique identifier or can ask the server to provide it a unique identifer. 或者,您可以使用应用程序层逻辑(请记住应用程序位于TCP之上),客户端可以在其中使用唯一标识符,也可以要求服务器为其提供唯一标识符。 So, when the client comes back, it then tells the server that it has a identifier and it would like to resume that connection. 因此,当客户端返回时,它会告诉服务器它具有标识符,并且希望恢复该连接。 WIth that, the server can associated the new fd with the identifier that it had issued earlier. 为此,服务器可以将新的fd与它先前发布的标识符相关联。 Note that if the server issues an identifier, then it is easier to guarantee identifier uniqueness -- for example, the server could issue the identifier incrementally. 请注意,如果服务器发布标识符,则更容易保证标识符的唯一性-例如,服务器可以递增地发布标识符。

I assume some kind of chat-application that - when the user clicks on the App on his/her Android device - shows the last messages as history. 我假设有一种聊天应用程序-当用户单击其Android设备上的应用程序时-将最近的消息显示为历史记录。

The part of identifying the client is something you have to think from the design side, considering things like data privacy. 识别客户的部分是您必须从设计方面考虑到数据隐私等问题的考虑。 Let me explain a few alternatives: 让我解释一些替代方法:

  • Identify client by Address: This is a String you can get with client.getInetAddress().getHostAddress() . 通过地址标识客户端:这是您可以使用client.getInetAddress().getHostAddress()获得的字符串。 As the IP Address is something that can be reused in a DHCP environment and the hostname of an Android device is defined by Android that cannot by changed by the user, this identification method could be a good way but not necessarily always really the same client. 由于IP地址是可以在DHCP环境中重用的内容,并且Android设备的主机名是由Android定义的,因此用户无法更改,因此此标识方法可能是一个好方法,但不一定总是同一客户端。 What happens in your App, when another Android device is accidently indentified and gets the history of actually another user? 当意外识别出另一个Android设备并获取了另一个用户的历史记录时,您的应用程序会发生什么?
  • You might want to transfer the IMEI of the device as unique identifier to the server and use this to identify the user/App. 您可能希望将设备的IMEI作为唯一标识符传输到服务器,然后使用它来标识用户/应用程序。 See TelephonyManager for information how to use getDeviceId() . 有关如何使用getDeviceId()信息,请参见TelephonyManager
  • With the two identifications above you identify the user/device/app without letting the user know, that you do so. 使用上面的两个标识,您可以在不通知用户的情况下标识用户/设备/应用。 Depending on how sensitive the environment of your App is (eg Public German App vs. your private little helper App) this can be a legal issue. 根据您的应用程序环境的敏感程度(例如,公共德语应用程序与您的私人小助手应用程序),这可能是一个法律问题。 So, the way out here, is to create user accounts, let the user register, login, work with your App and logout. 因此,这里的出路是创建用户帐户,让用户注册,登录,使用您的App并注销。 You can then have a disclaimer that the user signs when he/she registers. 然后,您可以拥有免责声明,供用户在注册时签名。 Of course this is by far the most complex solution. 当然,这是迄今为止最复杂的解决方案。

In the end you need to store the history of messages. 最后,您需要存储消息的历史记录。 I would expand the line messageListener.messageReceived(message); 我将扩展messageListener.messageReceived(message);messageListener.messageReceived(message); and the method sendMessage(String message) to save the messages, for example in a file for each client. 以及方法sendMessage(String message)来保存消息,例如,将消息保存在每个客户端的文件中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM