简体   繁体   English

健壮的Java套接字编程

[英]Robust Java Socket Programming

My client application needs to be able to recover in several situations. 我的客户端应用程序需要能够在几种情况下恢复。 When the power is turned on the client reads the address and port from a file and attempts to connect to the server. 打开电源后,客户端将从文件中读取地址和端口,并尝试连接到服务器。 If this is the first time this client has been used on this host a default IP address is tried but this may be incorrect. 如果这是第一次在此主机上使用此客户端,则会尝试使用默认IP地址,但这可能不正确。 The user then needs to enter the correct IP address. 然后,用户需要输入正确的IP地址。 The port is hard coded. 端口是硬编码的。 The way it works now is a one second swing.Timer attempts to get the status of the server... 现在它的工作方式是摆动一秒钟。计时器试图获取服务器的状态...

statusTimer = new Timer(ONE_SECOND, new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        final byte GET_STATUS = 20;
        SendCommand(GET_STATUS, null);
    }
});
statusTimer.start();

If there is no connection the user is asked to connect... 如果没有连接,则要求用户连接...

private void SendCommand(byte command, byte[] parameters) {
    if ((null == socket) || (null == outputStream) || socket.isClosed())
        if (JOptionPane.YES_OPTION == 
            JOptionPane.showConfirmDialog(null, "Connect?")) 
            Connect();
            ...

private void Connect() {
    String s = (String) 
        JOptionPane.showInputDialog(null, "Enter IP Address", ipAddress);
    if (validateIp(s)) {
        ipAddress = s;
        connectTask = new ConnectTask();
        connectTask.start();
        ...

The socket is opened, the io streams are set, and an RxThread is started. 打开套接字,设置io流,并启动RxThread。

class ConnectTask extends Thread {
    @Override public void run() {
        try {
            if (null == socket) socket = new Socket(ipAddress, TCP_PORT);
            if (null == outputStream) outputStream = socket.getOutputStream();
            if (null == inputStream) inputStream = socket.getInputStream();
            if (null == rxThread) rxThread = new RxThread();
            ...

There are a few bad things that could happen at this point, for example: 此时可能会发生一些坏事,例如:
1. The server could be off when the client is turned on. 1.客户端打开时,服务器可能已关闭。 What is the best way for the client to automatically open the socket, set the io streams, and continue when the server is powered on? 客户端自动打开套接字,设置io流并在服务器开机时继续操作的最佳方法是什么?
2. In the same way, the server might see a power cycle during a read, write, or neither. 2.以相同的方式,服务器在读取,写入或两者都不执行期间可能会关闭并重新启动。 Is there a good way to automatically recover after power is restored? 恢复电源后,有没有一种自动恢复的好方法?
3. The IP address may need to be corrected as mentioned above. 3. IP地址可能需要如上所述进行更正。
It would be nice to handle these and other situations without requiring the user to close and open the client application or power cycle the system. 在不要求用户关闭和打开客户端应用程序或关闭系统电源的情况下,很好地处理这些情况和其他情况。 What kinds of approaches are needed for a bullet-proof java client socket? 防弹java客户端套接字需要哪种方法?
This and this are similar but deal with a server sockets 这个这个相似,但是处理服务器套接字

You need to be able to distinguish between first-time usage (when the server details may be wrong, and the user should be prompted) and later usage (when the server may just be down). 您需要能够区分首次使用(当服务器详细信息可能有误时,应提示用户)和以后的使用(当服务器可能刚刚停机时)。 You could save a file when the user first enters the IP, for example. 例如,您可以在用户首次输入IP时保存文件。

After that, you probably want something like: an inner loop where you attempt to connect to the server and read data, with a timeout. 在那之后,您可能想要类似:内部循环,尝试连接到服务器并读取数据,但超时。 If the socket is closed due to a network error then this can be caught with a try-catch block. 如果套接字由于网络错误而关闭,则可以使用try-catch块捕获该套接字。 Put all this into an outer loop so that you try again when disconnected. 将所有这些内容放入外部循环中,以便在断开连接时重试。

Depending on the details, and assuming the amount of data is small, it may well be easiest for your client to open a connection every time rather than attempting to maintain a connection, then sleep in between connections. 根据详细信息,并假设数据量很小,对于您的客户端而言,每次打开一个连接而不是尝试维护连接,然后在连接之间休眠都可能是最容易的。

If the server is unresponsive, your current code (which creates a new ConnectTask thread each second using a Timer) may end up creating multiple ConnectTasks, one created per second, each trying to connect in parallel, though it's hard to be certain from the partial code you posted. 如果服务器无响应,您当前的代码(每秒使用一个计时器每秒创建一个新的ConnectTask线程)可能最终创建多个ConnectTasks(每秒创建一个),每个ConnectTasks尝试并行连接,尽管很难从部分连接中确定您发布的代码。

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

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