有 Java 编程相关的问题?

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

C#Java之间的ClientServer通信

第一:我希望我的英语不是那么差(也许是格格英语;德语语法和英语词汇)

我正在用java为安卓编写一个服务器,它与运行在WindowsCE 5上的c#编写的客户端进行通信。最大的问题是,有时,尤其是或者只有在网络不稳定的情况下,当客户端发送数据时,我的java服务器仍然会阻塞accept方法。我通过关闭和打开虚拟路由器来模拟不稳定的网络,这两个设备都通过虚拟路由器进行通信。我还可以意识到,当网络打开并且我的服务器正在监听预期端口时,c#程序挂起在写或读方法中,或者抛出IOException

以下是客户端的源代码:

一些信息: 1.仅为测试发送10000条消息

static void Main(string[] args)
{
    string server = ...;
    int port = 12000;
    String outputStr = "";
    NetworkStream stream = null;
    for (int i = 0; i < 10000; i++)
    {
        TcpClient client = null;
        String messageToSend = ...
        try
        {
            IPAddress ipAddress = IPAddress.Parse(server);
            IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, port);
            AutoResetEvent connectDone = new AutoResetEvent(false);
            client = new TcpClient();
            client.Client.BeginConnect(ipEndPoint,
                new AsyncCallback(
                        delegate(IAsyncResult ar)
                        {
                            try
                            {
                                client.Client.EndConnect(ar);
                                connectDone.Set();
                            }
                            catch (Exception ex)
                            {}
                        }
                    ), client.Client);

                if (!connectDone.WaitOne(5000, false))
                {
                    outputStr = "NOTConnected";
                }
                Byte[] data = System.Text.Encoding.UTF8.GetBytes(messageToSend);
                stream = client.GetStream();
                try
                {
                    stream.Write(data, 0, data.Length);
                    data = new Byte[2048];
                    int bytes = stream.Read(data, 0, data.Length);
                    string responseData = System.Text.Encoding.UTF8.GetString(data, 0, bytes);
                    outputStr = responseData;
                }
                catch (IOException ex)
                {
                    outputStr = ex.Message;
                }
            }
        }
        catch (SocketException ex)
        {
            outputStr = ex.Message;
        }     
        catch (Exception ex)
        {
            outputStr = ex.Message;
        }
        finally
        {
            if (stream != null) stream.Close();
        }
        System.Threading.Thread.Sleep(200);
    }
    Console.WriteLine("\n Press Enter to continue... " + outputStr);
    Console.Read();
}

以及我的服务器源代码:

一些信息。我的servlet通常是一个内部类,首先检查设备是否连接到路由器。如果它开始在这里的一个港口。如果没有,则进入等待模式(请参阅_sendToSleep()。如果设备重新连接,活动可以通过notify将其唤醒。如果再次断开连接,活动将通过关闭socket导致SocketException,这样servlet就可以离开accept方法

public class ServletThread extends Thread {

    private int port;
    private ServerSocket serverSocket;
    private Socket socket;

    public ServletThread(int port) throws IOException {
        super();
        this.port = port;
        serverSocket = new ServerSocket(port);
    }

    private void checkConnectivity(BufferedWriter out) {
        try {
            String outgoingMsg = "connected";
            out.write(outgoingMsg);
            out.flush();
        } catch (IOException e) {
            Log.e(TAG, "connectivity exception " + e.getMessage());
        }
    }

    private void readStream(Scanner scanner) throws IOException {
        String str = "";
        while (scanner.hasNext()) {
            str += scanner.nextLine();
        }
        final String fTicket = str;
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (MyActivity.this.isFinishing()) {
                    return;
                }
                // do something
            }
        });
    }

    private void _sendToSleep() {       
        try {
            synchronized (this) {
                this.wait();
            }
        } catch (InterruptedException e) {
            this.interrupt();
        }
    }

    @Override
    public void interrupt() {
        super.interrupt();
        if (serverSocket != null) {
            try {
                serverSocket.close();
            } catch (IOException e) {
                Log.e(TAG, ""+e.getMessage());
            }
        }
    }

    @Override
    public void run() {
        try {
            serverSocket = new ServerSocket(port);
        } catch (IOException ex) {
            Log.e(TAG,""+ex.getMessage());
        }
        while (!isInterrupted()) {
            if (connectionState != NetworkInfo.State.CONNECTED) {
                _sendToSleep();
            } else {
                BufferedWriter out = null;
                Scanner scanner = null;
                try {
                    socket = serverSocket.accept();
                    out = new BufferedWriter(new OutputStreamWriter(
                                socket.getOutputStream()));
                    scanner = new Scanner(socket.getInputStream());
                    checkConnectivity(out);
                    readStream(scanner);
                } catch (IOException ex) {
                    Log.e(TAG, ex.getMessage() + "");
                } finally {
                    if (socket != null) {
                        try {
                            socket.close();
                        } catch (IOException e) {
                            Log.e(TAG, "exception on close socket " + e.getMessage());
                        }
                    }
                    if (scanner != null) {
                        scanner.close();
                    }
                    if (out != null) {
                        try {
                            out.close();
                        } catch (IOException e) {
                            Log.e(TAG, ""+e.getMessage());
                        }
                    }
                }
            }
        }
    }
}

在隔离错误后,我做了一些更改:

c#而不是stream=client。getStream

(using Stream = client.getStream()) {
    ...
    stream.WriteTimeout = 1000;
    stream.ReadTimeout = 1000;
    ...
}

在java中,_sendToSleep()中的变化

private void _sendToSleep() {
    if (serverSocket != null) {
        try {
            serverSocket.close();
        } catch (IOException e) {
            Log.e(TAG, "failed to close serverSocket " + e.getMessage());
        }
    }
    try {
        synchronized (this) {
            this.wait();
        }
    } catch (InterruptedException e) {
        this.interrupt();
    }
    try {
        serverSocket = new ServerSocket(port);
    } catch (IOException e) {
        Log.e(TAG, "failed to open serversocket " + e.getMessage());
    }
}

它变得更好了,这意味着我无法重现这个问题

我的问题是:

为什么客户会被吊死?(可能是servlet端和客户端在socketserver和wlan适配器之间多次重新连接后出现同步问题,导致servlet无法获取任何数据???) 我的改变能解决问题吗

提前感谢你


共 (0) 个答案