C#-Java之间的客户端 - 服务器通信

时间:2013-08-21 12:04:43

标签: c# java android

首先:我希望我的英语不是那么糟糕(也许它很有趣;德语语法有英语词汇)

我在java for android中编写一个服务器,它与在WindowsCE 5上运行的c#编写的客户端进行通信。最大的问题是,有时特别或者可能只有在网络不稳定时我的java服务器仍会阻塞accept-Method也在客户端发送数据时。我通过关闭和我的虚拟路由器模拟不稳定的网络,两个设备通过它进行通信。我也可以认识到c#-program在写入或读取方法中挂起,或者在网络开启且我的服务器在预期端口上听到时也会抛出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())。如果重新连接设备,活动可以通过通知唤醒它。如果它再次失去连接,那么Activity将通过关闭套接字导致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());
                        }
                    }
                }
            }
        }
    }
}

隔离bug之后,我做了一些更改:

c#而不是stream = client.getStream

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

在_sendToSleep()中的java更改

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

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

我的问题:

为什么客户端挂起? (重新连接几次后,socketserver和wlan-adapter之间的servlet端和客户端可能出现同步问题,这样servlet无法获取任何数据???) 并且我的更改可以解决问题。

期待你的感谢!

0 个答案:

没有答案