代号一 - 无法从真实设备上的套接字读取

Posted

技术标签:

【中文标题】代号一 - 无法从真实设备上的套接字读取【英文标题】:Codename One - Can't read from socket on real device 【发布时间】:2018-01-22 13:19:44 【问题描述】:

我正在使用 Codename One 开发一个 ios 应用程序。我扩展了 SocketConnection 类,以便从服务器接收数据。

class CustomSocketConnection extends SocketConnection 

    private OutputStream os;
    private InputStream is;
    private InputStreamReader isr;
    private String rawMessage;

    public CustomSocketConnection()
        os = null;
        is = null;
        isr = null;
        rawMessage = null;
    

    public synchronized String getRawMessage()
        return rawMessage;
    

    @Override
    public void connectionError(int errorCode, String message) 
        rawMessage = null;
        ToastBar.showErrorMessage("Error Connecting. ErrorCode: " + errorCode + " Message: " + message);
        System.out.println(">>>CustomSocketConnection, connectionError. Error Connecting. ErrorCode: " + errorCode + " Message: " + message);
    

    @Override
    public void connectionEstablished(InputStream is, OutputStream os) 
        System.out.println(">>>CustomSocketConnection, connectionEstablished");

        char termination = '\n';

        int length = 1024;
        char[] buffer = new char[length];
        byte[] bufferByte = new byte[length];
        StringBuilder stringBuilder = new StringBuilder();
        System.out.println(">>>CustomSocketConnection, connectionEstablished, prima del while");

        try 
            InputStreamReader isr = new InputStreamReader(is, "UTF-8");
            System.out.println(">>>CustomSocketConnection, connectionEstablished, prima della read");

            while(true)
                System.out.println(">>>CustomSocketConnection, loop di read, inizio");
                int read = isr.read();
                System.out.println(">>>CustomSocketConnection, loop di read, subito dopo la read");
                char c = (char) read;
                if (read == -1) rawMessage = null;

                System.out.println(">>>CustomSocketConnection, loop di read, letto: " + c);

                while(c != termination)
                    stringBuilder.append(c);
                    read = isr.read();
                    c = (char) read;
                    if (read == -1) rawMessage = null;
                
                rawMessage = stringBuilder.toString();
                if(rawMessage != null) doActions(rawMessage);

                //System.out.println(">>>CustomSocketConnection, connectionEstablished, ho letto: " + rawMessage + "FINE");
            


         
        catch (IOException ex) 
            System.out.println(">>>CustomSocketConnection, connectionEstablished, errore: " + ex.getMessage());
        

        System.out.println(">>>CustomSocketConnection, connectionEstablished, dopo il while"); 

    

    private void doActions(String msg)
        //do something

    

connectionEstablished 方法中,我使用 InputStreamReader 类的 read 方法从服务器读取数据。

如果我在模拟器上运行应用程序,它可以正常工作并从服务器接收数据。当我在真实设备(iPad mini,32 位设备,iOS 版本 8.1.1 12B435,more details here;iPhone 7s,64 位设备,iOS 版本 11.2.5 15D60)上启动应用程序时,读取方法不从服务器接收数据。其实read方法之前可以看到println打印出来的字符串,但是read方法之后就看不到println打印出来的字符串了。

问题不在于服务器端,因为我开发了一个 android 应用程序,它从同一台服务器接收数据。没有防火墙限制或其他网络限制:Android 应用和 Codename One 模拟器都在连接到服务器的同一本地网络或从另一个网络时接收数据。

怎么了?

【问题讨论】:

您的设备是否在同一个网络中?似乎与网络、wifi等有关 是的,同一个网络。 您使用的是什么 URL 和端口?也许您的开发机器上的防火墙阻止了外部通信? 我使用的是公共IP地址和8888端口。我将运行模拟器的电脑和iPad连接到同一个网络:模拟器读取数据,iPad没有接收数据。 这到底卡在哪里了?它是在查找期间卡住还是什么也没发生。我注意到您使用了System.out 而不是Log.p(),这样您就可以在事后查看日志。使用网络监控工具检查流向服务器的流量也有助于查明问题。 【参考方案1】:

使用 InputStream 而不是 InputStreamReader 解决。

@Override
public void connectionEstablished(InputStream is, OutputStream os) 
    System.out.println(">>>CustomSocketConnection, connectionEstablished");

    char termination = '\n';

    StringBuilder stringBuilder = new StringBuilder();
    System.out.println(">>>CustomSocketConnection, connectionEstablished, prima del while");

    try 
        System.out.println(">>>CustomSocketConnection, connectionEstablished, prima della read");

        while(true)
            System.out.println(">>>CustomSocketConnection, loop di read, inizio");
            int read = is.read();
            System.out.println(">>>CustomSocketConnection, loop di read, subito dopo la read");
            char c = (char) read;
            if (read == -1) rawMessage = null;

            System.out.println(">>>CustomSocketConnection, loop di read, letto: " + c);

            while(c != termination)
                stringBuilder.append(c);
                read = is.read();
                c = (char) read;
                if (read == -1) rawMessage = null;
            
            rawMessage = stringBuilder.toString();
            if(rawMessage != null) doActions(rawMessage);

            //System.out.println(">>>CustomSocketConnection, connectionEstablished, ho letto: " + rawMessage + "FINE");
        


     
    catch (IOException ex) 
        System.out.println(">>>CustomSocketConnection, connectionEstablished, errore: " + ex.getMessage());
    

    System.out.println(">>>CustomSocketConnection, connectionEstablished, dopo il while"); 


谁能解释一下为什么它与 InputStream 一起工作?

【讨论】:

我在您的代码中错过了这一点。 InputStreamReader 将对read() 的调用转换为缓冲调用,因为它需要将字节转换为字符。为此,您通常需要不止一个。此外,缓冲读取要快得多。因此,当您编写 read() 时,它会转换为 read(arrayOf8192Bytes)

以上是关于代号一 - 无法从真实设备上的套接字读取的主要内容,如果未能解决你的问题,请参考以下文章

PHP 从 Windows 机器上的套接字读取

ORACLE数据连接报错无法从套接字读取更多的数据怎么解决

java连oracle中连不上,错误是“无法从套接字读取更多的数据”,是啥问题?

Oracle 启动SQL Developer提示无法从套接字读取更多的数据

java.sql.SQLException: 无法从套接字读取更多的数据

mIRC 套接字从 url 读取文本