2

I have a simple Java Server Socket but when I connect to it with a C#.Net Socket and Send to the Java Socket it blocks and I have to shutdown the .Net socket send for it to stop blocking. This them means I have to close the socket after each communication. Where am i going wrong?

socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPEndPoint ip = new IPEndPoint(IPAddress.Parse(ipAddress.Text), 8089);
                socket.Connect(ip);
 byte[] b = Encoding.UTF8.GetBytes(json);
            socket.Send(b, b.Length, SocketFlags.None);
        socket.Shutdown(SocketShutdown.Send);
        int timeout = 0;
        while (socket.Available == 0)
        {
            Thread.Sleep(100);
            timeout++;
        }


        string response = "";
        byte[] buffer = new byte[8192];
        int total = 0;
        while (socket.Available > 0)
        {
            int len = socket.Receive(buffer);
            total += len;
            response = response + (Encoding.UTF8.GetString(buffer, 0, len));
            buffer = new byte[1024];
            if (socket.Available == 0) Thread.Sleep(250);
        }
        MessageBox.Show(response);
        return response.Trim();

    }

ServerSide

clientSocket = serverSocket.accept();
        clientSocket.setKeepAlive(true);
        Log.d("DbThread","client Connected");

        br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()),8192);
        bo = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()),8192);

        Thread.sleep(100);
        char[] buffer = new char[8192];

        int len=0;
        String build = "";
        while((len = br.read(buffer))>0){

            build = build + new String(buffer);
            buffer = new char[8192];
        }

        JSONObject json = new JSONObject(build.trim());
        Log.d("input",build.trim());
        String output = "";
        Gson gson = new Gson();
        switch(json.getString("classType").charAt(0))
        {
        case 'Q':
            Log.d("classType","Q");
            Query query = gson.fromJson(build.trim(), Query.class);
            output = query.executeToJson();Log.d("Query","end");break;

        case 'I':
            Log.d("classType","I");
            Insert insert = gson.fromJson(build.trim(), Insert.class);
            output = insert.executeToJson();break;

        case 'U':
            Log.d("classType","U");
            Update update = gson.fromJson(build.trim(), Update.class);
            output = update.executeToJson();break;

        case 'D':
            Log.d("classType","D");
            Delete delete = gson.fromJson(build.trim(), Delete.class);
            output = delete.executeToJson();break;

        }       



        bo.write(output);
        bo.flush();

        Log.d("Query",output);

    br.close();
4

1 回答 1

1

首先,检查Available循环退出条件是不安全的;告诉您的只是本地缓冲的内容;这与流的结束无关。

其次,添加 aThread.Sleep不是一种理想的方法;只是阅读或接收;这将阻塞,直到一些数据可用;通常你只是一个循环读取或接收。

它会挂起的一个明显情况是:如果另一台机器没有发送任何回复;在这种情况下,它将永远位于最顶层的循环中。

补充说明:

  • 不需要buffer每次迭代都分配一个新的;之前的 8192 缓冲区还是可以的;重新使用它
  • 不应该假设您的缓冲区中有整个字符,尤其是因为您使用的是 UTF8;您的缓冲区可能具有字符的多字节表示的一部分;在开始解码之前确保您拥有完整的消息/帧通常更容易

我个人会通过添加大量调试输出和网络嗅探器来对此进行调查。

于 2012-08-02T14:07:26.367 回答