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

标签 c# java .net sockets

我有一个简单的 Java 服务器套接字,但是当我使用 C#.Net 套接字连接到它并发送到 Java 套接字时,它会阻塞,我必须关闭 .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();

最佳答案

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

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

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

补充说明:

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

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

关于c# - 发送到 Java 套接字时 .Net 套接字阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11778634/

相关文章:

c# - 调用 `Environment.GetEnvironmentVariable`影响后续调用

c# - 使用日期将 JQuery JSON 发送到 WCF REST

c# - 使用 Azure AD 对 Twilio 请求进行身份验证

c# - Unity GameAnalytics 插件在 iOS 构建上失败

java - OpenCV 中相机捕获的图像为全黑

java - onActivityResult 没有给出任何结果

Java $APP_PACKAGE 路径名变量不起作用

C#如何调用base中的一个方法?

.net - 如何为 Oracle 数据库创建 Visual Studio 数据库项目?

c# - 不理解 RunInstaller 属性