发送到Java套接字时.Net套接字阻塞

时间:2012-08-02 13:37:52

标签: c# java .net sockets

我有一个简单的Java Server Socket但是当我使用C#.Net Socket和发送到Java Socket连接它时它会阻塞,我必须关闭.Net套接字发送它才能阻止它。这意味着我必须在每次通信后关闭套接字。我哪里错了?

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

    }

服务器侧

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

1 个答案:

答案 0 :(得分:1)

首先,将Available视为循环退出条件是不安全的;所有这些都告诉你本地缓冲的是什么;这与流的结束无关。

其次,添加Thread.Sleep并不是理想的做法;只是阅读或接受;这将阻止某些数据可用;通常你只是在阅读或接收上循环。

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

附加说明:

  • 不应该每次迭代需要分配一个新的buffer;以前的8192缓冲区仍然没问题;重复使用
  • 不应该假设你的缓冲区中包含完整的字符,特别是因为你使用的是UTF8;你的缓冲区可能有一个字符的多字节表示的一部分;在开始解码之前,通常更容易确保您拥有整个消息/帧

我个人会通过添加大量调试输出和网络嗅探器来研究这个问题。