1

在超出设计人员预期的正常操作步骤的情况下,我已经厌倦了手臂摔跤的 Android。我想补充一点,接口契约也是行为性的,而不仅仅是保持参数相同的情况。比如 HONEYCOMB 之后对 AsyncTask 操作的改变:默认是序列化的方式。

问题:

我们开发专有应用程序;它们可能永远不会出现在 Play 商店中,我们拥有运行它们的所有设备。我们使用 android 设备来驱动通过 RS 232 或以太网接口连接的各种类型的硬件。

背景:

我有一种情况,我们有一个使用 TCP/IP 套接字定期(异步)连接到 android 平板电脑的外部设备。因为每个连接都有相关的状态信息,所以我需要在(至少)两个活动期间保持 IP 套接字正常运行。一般流程是:

:start
Device ----> Connect (to android device)---->Tablet 
Device ----> Send session info-------------->Tablet
Device <---- Send response<------------------Tablet
(a new activity may start here)
Device <---- Send instruction<---------------Tablet 
Device ----> Send response------------------>Tablet
Device <---- Send instruction<---------------Tablet
Device ----> Send response------------------>Tablet
Device <---- Send instruction<---------------Tablet
Device ----> Send response------------------>Tablet
goto start

以上内容略有解释,但它给出了系统的要点。

最初的方法是让一个进程内服务运行(与应用程序相关联),使用一个单独的线程处理异步连接并编组进出设备的请求。共享对象维护服务器线程和连接的状态。

然而,每隔一段时间,前台应用程序就需要向设备发送命令。为此,它确保服务器和设备之间存在现有连接,锁定可重入锁(以阻止对套接字的并发访问)并启动 AsyncTask 将命令发送到设备并等待响应,几乎在所有情况下,都会在几毫秒内返回。显然,我不能在 UI 线程上发出套接字接收,否则会导致“NetworkOnMainThreadException”(发送工作正常。另外,我想避免轮询结果,因为它俗气且效率低下。因此,我发出“ get(1000L)”,它会在设备响应或在 Android“无响应”错误出现之前超时立即返回。

这种方法在 Gingerbread 上非常有效,但我们现在需要将系统升级到 ICS 或更好。不幸的是,当我在 Honeycomb 以北的 Android 版本上发出 AsyncTask 时,它从未命中 doInBackground。经调查,默认情况下,在 AsyncTask 上发出的任何内容一次只允许一个线程运行,而且似乎主服务线程可能算作额外线程。(虽然我还没有找到任何明确的说法)。

我不想重写整个设备接口,因为它会影响多个产品,而且它们都必须重新测试,考虑到硬件的性质,这将是一个非常耗时的过程。

所以,我的问题是双重的:

1) 有没有人知道一种方法可以将 AsyncTask 行为修改为具有较少线程限制而无需大量代码更改的东西?

2)如果没有,是否有更好的模式来解决这类问题,因为如果我必须重新编写,我想正确地做;最好不用轮询任何东西?

我不能完整地发布代码,因为它都包含在 NDA 协议中,但是如果对结构有特定的问题,我可能会删掉一些片段。

4

3 回答 3

1

我认为您在这里看到的是各种 Android 版本上线程的一些潜在变化。我猜他们这样做是为了让线程可以在 Android 3 的不同内核上运行。?而且,由于很少有程序员擅长实际并发,如果再次关闭,他们就会关闭。我想如果你看一下上面的帖子,你也许可以让事情恢复原状。

顺便说一句,这解决了问题一而不是二。

于 2013-08-09T19:04:14.563 回答
1

(1):简单的做法是使用AsyncTask.executeOnExecutor(Executor exec, Params... params),你可以自己配置这个。

(2):一种模式是使用线程和处理程序的标准 Java 并发。这是一个很好的起点。您将分拆一个后台线程并为它提供一个 UI 处理程序,以便它可以将消息传回。

另一种模式是使用可能不像 java 并发那样适合任务的 Android服务。

于 2013-08-09T19:15:02.730 回答
0

这是所有代码 - 似乎可以正常工作socketserver.zip

这是业务端:

package com.retailsci.socketserver;

/**
 * Created with IntelliJ IDEA.
 * User: paul
 * Date: 2013/08/12
 * Time: 9:06 PM
 * To change this template use File | Settings | File Templates.
 */
import java.lang.ref.WeakReference;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.lang.InterruptedException;
import java.util.Enumeration;
import android.os.AsyncTask;
import java.io.BufferedInputStream  ;
import java.io.BufferedOutputStream ;
import java.io.OutputStreamWriter   ;

import android.app.Activity;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle ;
import android.os.IBinder ;
import android.os.RemoteException ;
import android.view.View ;
import android.view.View.OnClickListener ;
import android.widget.Button ;
import android.widget.Toast ;
import android.widget.TextView ;
import android.util.Log ;
import android.os.Handler;
import org.apache.http.conn.util.InetAddressUtils;

public class ServerThread implements Runnable
{
    public static final String    TAG = "RetailScience::ServerThread"    ;
    public static final int       READ_OPERATION        = 1 ;
    public static final int       WRITE_OPERATION       = 2 ;
    public static final int       READLENGTH_OPERATION  = 3 ;
    public static final int       WRITELENGTH_OPERATION = 4 ;

    int                           ServerPort     ;
    ServerSocket                  serverSocket   ;
    Socket                        client         ;
    boolean                       Connected      ;
    String                        IPAddress      ;
    CircularByteBuffer            InDataBuffer   ;
    CircularByteBuffer            OutDataBuffer  ;

    public ServerThread (int ServerPort)
    {
        Log.v(TAG, "constructor - start") ;

        this.ServerPort = ServerPort ;

        IPAddress = IPv4Address() ;

        Log.v(TAG, "constructor - end") ;
    }

    public boolean isConnected ()
    {
        return(Connected) ;
    }

    public String getIPAddress ()
    {
        return (IPAddress) ;
    }

    public void closeAll ()
    {
        Connected = false ; /* set the connection state */

        Log.v(TAG, "Closing all the sessions");

        try
        {
            client.close () ;
        }
        catch (Exception e)
        {
            final String error = e.getLocalizedMessage();
            Log.e(TAG, "Socket Thread - Exception on Client Close " + e.toString());
        }

        try
        {
            serverSocket.close () ;
        }
        catch (Exception e)
        {
            final String error = e.getLocalizedMessage();
            Log.e(TAG, "Socket Thread - Exception on serverSocket Close " + e.toString());
        }

        serverSocket  = null ;
        client        = null ;
        InDataBuffer  = null ;
        OutDataBuffer = null ;

        System.gc() ;

        /* Make sure the other threads can have a go now */
        Thread.yield () ;
    }

    public boolean write (byte [] data, int offset, int length)
    {
        boolean okay = false ;

        if (isConnected ())
        {
            try
            {
                OutDataBuffer.getOutputStream().write (data, offset, length) ;
                okay = true ;
                Thread.yield() ; /* Give the background thread a chance */
            }
            catch (Exception e)
            {
                final String error = e.getLocalizedMessage();
                Log.e(TAG, "UI Thread - Probably a Connection Exception " + e.toString());
            }
        }

        return (okay) ;
    }

    public void flush () /* Clear out anything in the IC buffers */
    {
        if (isConnected ())
        {
            try
            {
                int  BytesReady = 0 ;

                do
                {
                    Thread.yield() ; /* Give the background thread a chance */

                    BytesReady = InDataBuffer.getInputStream().available () ;

                    Log.v(TAG, "FLUSH bytes" + BytesReady) ;

                    if (BytesReady > 0)
                    {
                        byte[] junk = new byte [BytesReady] ;
                        InDataBuffer.getInputStream().read (junk, 0, BytesReady) ;
                    }
                    Thread.sleep (50) ; /* Give the other thread time to pull */
                                        /* anything else out of the IC buffer */
                }
                while (BytesReady > 0);

            }
            catch (Exception e)
            {
                final String error = e.getLocalizedMessage();
                Log.e(TAG, "UI Thread - Probably a Connection Exception " + e.toString());
            }
        }
    }


    public int available ()
    {
        int  BytesReady = -1 ;

        if (isConnected ())
        {
            try
            {
                BytesReady = InDataBuffer.getInputStream().available () ;

                if (BytesReady > 0)
                {
                    Log.v(TAG, "Bytes in incoming buffer " + BytesReady) ;
                }
            }
            catch (Exception e)
            {
                final String error = e.getLocalizedMessage();
                Log.e(TAG, "UI Thread - Probably a Connection Exception " + e.toString());
            }
        }

        return (BytesReady) ;
    }

    public int read (byte [] data, int offset, int length) throws IOException
    {
        int  BytesRead = -1 ;

        if (isConnected ())
        {
            Log.v(TAG, "*********  reading data " + length) ;
            try
            {
                BytesRead           = 0 ;
                int totalBytesRcvd  = 0 ; // Total bytes received so far

                while (totalBytesRcvd < length)
                {
                    if ((BytesRead =
                         InDataBuffer.getInputStream().read (data,
                                                             totalBytesRcvd + offset,
                                                             length - totalBytesRcvd)) == -1)
                    {
                        Log.e(TAG, "UI Thread Connection Exception in Read");
                        throw new SocketException("Connection closed prematurely");
                    }

                    Log.v(TAG, "*********  bytes read " + BytesRead) ;
                    totalBytesRcvd += BytesRead ;

                    Log.v(TAG, "*********  total bytes read " + totalBytesRcvd) ;
                }
                BytesRead = length ;
            }
            catch (Exception e)
            {
                final String error = e.getLocalizedMessage();
                Log.e(TAG, "UI Thread - Probably a Connection Exception " + e.toString());
            }
        }

        return (BytesRead) ;
    }

    //---get the local IPv4 address---
    // Taken from "Android(TM) Application Development Cookbook", by Wei-Meng Lee
    // p. 212
    // (Very useful book by the way)
    private String IPv4Address()
    {
        try {
            for (Enumeration<NetworkInterface> networkInterfaceEnum = NetworkInterface
                    .getNetworkInterfaces(); networkInterfaceEnum
                    .hasMoreElements();)
            {
                NetworkInterface networkInterface = networkInterfaceEnum.nextElement();

                for (Enumeration<InetAddress> ipAddressEnum
                     = networkInterface.getInetAddresses(); ipAddressEnum.hasMoreElements();)
                {
                    InetAddress inetAddress = (InetAddress) ipAddressEnum.nextElement();
                    // ---check that it is not a loopback address and
                    // it is IPv4---
                    if (!inetAddress.isLoopbackAddress()
                        &&
                        InetAddressUtils.isIPv4Address(inetAddress.getHostAddress()))
                    {
                        return inetAddress.getHostAddress();
                    }
                }
            }
        }
        catch (SocketException e)
        {
            Log.e(TAG, "IPv4Address " + e.toString());
        }
        return null;
    }

    public void run ()
    {
        try
        {
            if (IPAddress != null)
            {
                Log.v(TAG, "Starting...");
                // handler.post(new Runnable()
                //     {
                //          @Override
                //          public void run()
                //          {
                //              textView1.setText(textView1.getText()
                //                                + "Server listening on IP: " + SERVER_IP
                //                                + "\n");
                //          }
                //     });

                //---create an instance of the server socket---
                //--- Allow 2 outstanding connections
                serverSocket = new ServerSocket(ServerPort, 1);

                /* allow the socket to be reused - or we'll get INUSE exception*/
                serverSocket.setReuseAddress(true) ;

                int Counter = 0 ;
                Log.v(TAG, "Server Thread Running");

                while (true)
                {
                    //---wait for incoming clients---
                    Socket client = serverSocket.accept();

                    Log.v(TAG, "Connection Detected");
                    Connected = true ; /* set the connection state */

                    //---the above code is a blocking call;
                    // i.e. it will block until a client connects---
                    try
                    {
                        InDataBuffer                                = new CircularByteBuffer() ;
                        OutDataBuffer                               = new CircularByteBuffer() ;

                        BufferedInputStream         InStream      = new BufferedInputStream   (client.getInputStream()) ;
                        BufferedOutputStream        OutStream     = new BufferedOutputStream  (client.getOutputStream()) ;
                        int                         BytesDataBuffer ;

                        while (true)
                        {
                            if (Counter >= 1500) /* About 15 seconds */
                            {
                                /* Done' print this out too often */
                                Counter = 0 ;
                                Log.v(TAG, "Server Thread Running");
                            }
                            ++Counter ;

                            BytesDataBuffer = InStream.available() ;

                            if (BytesDataBuffer > 0)
                            {
                                Log.v(TAG, "Reading Data Bytes " + BytesDataBuffer);

                                byte [] TempBuffer = new byte [BytesDataBuffer] ;

                                InStream.read (TempBuffer, 0, BytesDataBuffer) ;
                                InDataBuffer.getOutputStream().write (TempBuffer, 0, BytesDataBuffer);

                                Log.v(TAG, "Read Data Bytes " + BytesDataBuffer);
                            }

                            BytesDataBuffer = OutDataBuffer.getInputStream().available() ;

                            if (BytesDataBuffer > 0)
                            {
                                Log.v(TAG, "Writing Data Bytes " + BytesDataBuffer);

                                byte [] TempBuffer = new byte [BytesDataBuffer] ;

                                OutDataBuffer.getInputStream().read (TempBuffer, 0, BytesDataBuffer) ;
                                OutStream.write (TempBuffer, 0, BytesDataBuffer);
                                OutStream.flush() ; /* Make sure the buffer is empty */

                                Log.v(TAG, "Wrote Data Bytes " + BytesDataBuffer);
                            }

                            Thread.sleep(100) ; /* Always yield for a bit */
                        }
                    }
                    catch (Exception e)
                    {
                        Log.e(TAG, "Socket Thread - Read Exception " + e.toString());
                        Connected = false ; /* set the connection state */
                    }

                } /*    while (true)    */
            }
            else
            {
                Log.e(TAG, "Socket Thread - No Network Capability");
                Connected = false ; /* set the connection state */
            }
        }
        catch (Exception e)
        {
            Log.e(TAG, "Socket Thread - Probably a Connection Exception" + e.toString());
            Connected = false ; /* set the connection state */
        }

        closeAll () ;
        Log.v(TAG, "*********************************************** Socket Thread - Connection Terminated");
        Log.v(TAG, "*********************************************** Socket Thread - Connection Terminated");
        Log.v(TAG, "*********************************************** Socket Thread - Connection Terminated");
        Log.v(TAG, "*********************************************** Socket Thread - Connection Terminated");
    }
}

读取和写入的示例位于:DeviceIF.java(在 zip 文件中)但是,这里有一些主要的原语:

    ServerThread                  SocketIF ;
    Thread                        BackgroundThread  ;


To start it
          SocketIF         = new ServerThread (12347) ; /* 12347 is the server I/C port */
          BackgroundThread = new Thread(SocketIF);
          BackgroundThread.setDaemon(true) ; /* Make this a Daemon Thread */
          BackgroundThread.start();


To stop it                
          SocketIF.closeAll () ;
          Thread.yield () ; /* give the thread time to find out it's dead */

          if (BackgroundThread != null)
          {
             if (BackgroundThread.isAlive())
             {
                 BackgroundThread.interrupt (); /* Get rid of the thread */
                 Thread.yield () ; /* give the thread time to find out it's dead */
             }
          }

To read
        try
        {
            if (SocketIF.isConnected ())
            {
                byte []   ResponseBuffer = new byte [7] ;
                int Result = SocketIF.read (ResponseBuffer, 0, 7) ;
            }   
        }
        catch (Exception e)
        {
            final String error = e.getLocalizedMessage() ;
            Log.e(TAG, "Exception : " + error);
        }

To Write
       int Result = ERROR_FAILED ;

        try
        {
            if (SocketIF.isConnected ()) /* see if it's still open */
            {
                // flushICData () ; Good idea to do this before you issue a request

                int             RequestLen = 0 ;
                final byte []   RequestBuffer  = new byte [20] ;

                RequestBuffer [RequestLen++] = (byte) 0 ;  /* This will eventually hold the length */
                RequestBuffer [RequestLen++] = (byte) '1' ;

                RequestBuffer [0] = (byte) ((RequestLen - 1) & 0xFF) ; /* Put in the length one byte's enough */

                SocketIF.write (RequestBuffer, 0, RequestLen) ;

                Result = ERROR_OKAY ;
            }
            else
            {
                Result = ERROR_NO_CONNECTION ;
            }
        }
        catch (Exception e)
        {
            final String error = e.getLocalizedMessage() ;
            Log.e(TAG, "Exception : " + error);
            Result = ERROR_EXCEPTION ;
        }

在我获得大量仇恨之前,我已经意识到架构中的一些缺陷;我保持简单以使其更易于理解(这就是我没有将读/写内容包装在流中的原因)。我也没有在读取中设置超时,但这将是一个轻而易举的补充。

我从其他来源借来的代码在来源中注明:

  • 工作计时器 - 使用是因为从滴答事件中取消默认的 android CountdownTimer 时出现问题 循环缓冲区 - 用于提供一个很好的简单循环缓冲区流以允许从服务器进行异步读取和写入。IP4Addess 代码来自 Android(TM) Application Development Cookbook”,作者 Wei-Meng Lee,第 212 页(顺便说一句很棒的书)

(我无法将 URL 链接放入后面的代码,因为我没有足够的代表来发布两个以上的 f* * * 链接)

出于说明的目的,如果在写入数据流和获得响应之间存在显着延迟,以下是处理传入数据的方法。这是从 Countdowntimer 中的 onTick 事件调用的(在我的情况下是 Workingtimer,因为上面提到的定时器取消问题)

protected void TickHandler ()
{
    try
    {
        /* See if we have connected yet */
        if (TerminalIF.isConnected ())
        {
            /* See if we have connected yet */
            Button btn ;

            btn = (Button) findViewById (R.id.getpinbutton);
            btn.setEnabled(true) ;

            btn = (Button) findViewById (R.id.displaybutton);
            btn.setEnabled(true) ;

            btn = (Button) findViewById (R.id.getcardstatebutton);
            btn.setEnabled(true) ;

            btn = (Button) findViewById (R.id.rebootbutton);
            btn.setEnabled(true) ;

            btn = (Button) findViewById (R.id.pingbutton);
            btn.setEnabled(true) ;

            if (TerminalIF.responseReady ())
            {
                byte [] DataResult = TerminalIF.ReceivePacket () ;
                Log.v(TAG, "Data Received") ;

                Toast.makeText(getApplicationContext(),
                               "Device Data Received",
                               Toast.LENGTH_SHORT).show() ;

                resetTimer (DEFAULT_INPUT_TIMER_TIMEOUT) ;
            }
        }
    }
    catch (Exception e)
    {
        final String error = e.getLocalizedMessage() ;
        Log.e(TAG, "Exception : " + error);
    }
}

是的,我可以使用 AsyncTasks 和处理程序来完成它,但这是一个直接的插件模块,几乎可以在任何地方使用,几乎不需要修改。转换成服务也很容易。

而且,在我因无关紧要、冗长或回答我自己的问题而被指责之前,我只是想我会分享这项工作。

最后一件事,这里有一个小测试工具可以试用:

密码键盘.java

import java.io.*;
import java.net.*;
import java.lang.* ;

public class PINPad
{
    InputStream  in  ;
    OutputStream out ;

    byte [] receive (int len) throws IOException
    {
        byte [] result = null ;

        if (len > 0)
        {
            byte [] temp = new byte [len] ;

            // Receive the same string back from the server
            int totalBytesRcvd = 0; // Total bytes received so far
            int bytesRcvd ;          // Bytes received in last read

            while (totalBytesRcvd < temp.length)
            {
              if ((bytesRcvd = in.read(temp, totalBytesRcvd, temp.length - totalBytesRcvd)) == -1)
              {
                  System.out.println("Error on receive");
                  throw new SocketException("Connection closed prematurely");
              }
              else
              {
                  System.out.println("Received " + bytesRcvd + " bytes");
              }

              totalBytesRcvd += bytesRcvd;
            } // data array is full

            result = temp ;
        }

        return result ;
    }

    void send (byte [] data, int offset, int len) throws IOException
    {
        System.out.println("Sending.... " + len + " bytes");
        if (len > 0)
        {
            try
            {
                out.write (data, offset, len) ;
            }
            catch (Exception e)
            {
                System.out.println("Error on send");
                throw new SocketException("Connection closed prematurely");
            }
        }
        System.out.println("Sent " + len + " bytes");
    }

    void loop (Socket  echoSocket)
    {
        boolean okay = true ;

        try
        {
            in  = echoSocket.getInputStream();
            out = echoSocket.getOutputStream();
        }
        catch (Exception e)
        {
            okay = false ;
        }

        while (okay)
        {
            try
            {
                System.out.println("Receive length");
                byte [] len = receive (1) ;

                int packetlength = (int) len[0] ;
                System.out.println("Subsequent packet length = " + packetlength);


                byte [] packet = receive (packetlength) ;

                System.out.println("Got a packet of = " + packet.length);

                char    packettype = (char) packet [0] ;
                byte [] retbuf = new byte [50] ;
                int     reqlen = 0 ;

                switch (packettype)
                {
                    case 'A' :  /* PING */
                        System.out.println("==== PING");
                        retbuf [reqlen++] = (byte) 0 ;  /* placeholder for the length */
                        retbuf [reqlen++] = (byte) packettype ;
                        retbuf [reqlen++] = (byte) '0' ;   /* Error code  = OK */
                        retbuf [0]        = (byte) (reqlen - 1) ;  /* Now put the length in */

                        send(retbuf, 0, reqlen);
                        break ;

                    case 'B' : /* GET PIN */
                        System.out.println("==== GET PIN");
                        retbuf [reqlen++] = (byte) 0 ;  /* placeholder for the length */
                        retbuf [reqlen++] = (byte) packettype ;
                        retbuf [reqlen++] = (byte) '0' ;   /* Error code  = OK */
                        retbuf [0]        = (byte) (reqlen - 1) ;  /* Now put the length in */

                        send(retbuf, 0, reqlen);
                        break ;

                    case 'C' : /* GET CARD STATE */
                        System.out.println("==== GET CARD STATE");
                        retbuf [reqlen++] = (byte) 0 ;  /* placeholder for the length */
                        retbuf [reqlen++] = (byte) packettype ;
                        retbuf [reqlen++] = (byte) '0' ;  /* Error code  = OK */
                        retbuf [reqlen++] = (byte) '1' ;  /* Card is present */
                        retbuf [0]        = (byte) (reqlen - 1) ;  /* Now put the length in */

                        send(retbuf, 0, reqlen);
                        break ;

                    case 'D' : /* DISPLAY */
                        System.out.println("==== DISPLAY");
                        retbuf [reqlen++] = (byte) 0 ;  /* placeholder for the length */
                        retbuf [reqlen++] = (byte) packettype ;
                        retbuf [reqlen++] = (byte) '0' ;  /* Error code  = OK */
                        retbuf [0]        = (byte) (reqlen - 1) ;  /* Now put the length in */

                        send(retbuf, 0, reqlen);
                        break ;

                    case 'E' : /* REBOOT */
                        System.out.println("==== REBOOT");
                        okay = false ;
                        break ;

                    case 'F' : /* CLOSE */
                        System.out.println("==== CLOSE SESSION");
                        okay = false ;
                        break ;

                    default :
                        System.out.println("==== UNKNOWN!!!!!!");
                        retbuf [reqlen++] = (byte) 0 ;  /* placeholder for the length */
                        retbuf [reqlen++] = (byte) packettype ;
                        retbuf [reqlen++] = (byte) '3' ;  /* error */
                        retbuf [0]        = (byte) (reqlen - 1) ;  /* Now put the length in */

                        send(retbuf, 0, reqlen);
                        break ;
                }
            }
            catch (Exception e)
            {
                okay = false ;
            }
        }

        try
        {
            out.close();
            in.close();
        }
        catch (Exception e)
        {
            okay = false ;
        }
    }


    public static void main(String[] args)
    {
        Socket          echoSocket = null;
        PINPad          IF = new PINPad () ;

        while (true)
        {
            try
            {
                echoSocket = new Socket("192.168.168.106", 12347);

                // out = new PrintWriter(echoSocket.getOutputStream(), true);
                // in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));

                if (echoSocket != null)
                {
                    System.out.println("Connected to remote");
                    IF.loop (echoSocket) ;

                    echoSocket.close();
                    System.out.println("Waiting for next connection");
                }
            }
            catch (UnknownHostException e)
            {
                System.err.println("Don't know about host: 192.168.168.107.");
                // System.exit(1);
            }
            catch (IOException e)
            {
                System.err.println("Couldn't get I/O for the connection to: 192.168.168.107.");
            }
            catch (Exception e)
            {
                System.err.println("Couldn't get I/O for the connection to: 192.168.168.107.");
            }

            try
            {
                Thread.sleep (1000) ;
            }
            catch (Exception e)
            {
                System.err.println("Thread Interrupted....");
                System.exit(1);
            }
        }
    }
}
于 2013-08-13T20:34:27.887 回答