1

I'm developing an iOS app, using Codename One. I extended the SocketConnection class, in order to receive data from a server.

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

    }
}

In the connectionEstablished method, I read data from server, using the read method of the InputStreamReader class.

If I run the app on the simulator, it works properly and it receives data from server. When I launch the app on real devices (iPad mini, 32-bit device, iOS version 8.1.1 12B435, more details here; iPhone 7s, 64-bit device, iOS version 11.2.5 15D60), the read method doesn't receive data from server. In fact, I can see the string printed by the println before the read method, but I can't see the string printed by the println after the read method.

The issue is not server-side, because I developed an Android app and it receive data from the same server. There aren't firewall restrictions or other network limitations: Android app and the Codename One simulator both receive data when connected on the same local network of the server or from another one.

What's wrong?

A M
  • 831
  • 1
  • 14
  • 26
  • Is your device in same network ? Seems to be something related to network, wifi, etc – GIJOW Jan 22 '18 at 13:46
  • Yes, same network. – A M Jan 22 '18 at 13:53
  • What URL and port are you using? Maybe the firewall on your development machine is blocking external communication? – Shai Almog Jan 23 '18 at 05:24
  • I'm using a public IP address and the port 8888. I connected the pc running the simulator and the iPad to the same network: the simulator reads data, the iPad doesn't receive data. – A M Jan 23 '18 at 07:28
  • Where is this stuck exactly? Is it stuck during lookup or is nothing happening at all. I noticed you used `System.out` instead of `Log.p()` which would allow you to review the logs after the fact. Using a network monitor tool to inspect the traffic going to the server would also help in pinpointing the issue. – Shai Almog Jan 23 '18 at 08:40
  • @ShaiAlmog In device logs, I can see the string printed by the System.out.println() before the read method, but I can't see that afted the read method. Moreover. I used Microsoft Network Monitor to inspect the traffic on the server machine. It correctly sends data in both cases (on simulator and on device). Any suggestions? – A M Jun 11 '18 at 15:12
  • Did you flush the written data in the server? If you write more than one byte does it change the results? Can you produce a standalone test case that reproduces this? – Shai Almog Jun 12 '18 at 04:16
  • @ShaiAlmog Yes, I flush data. I wrote more than one byte, but nothing changes. About test, what kind of test do you mean? – A M Jun 12 '18 at 08:11

1 Answers1

1

Solved using InputStream instead of 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"); 

}

Can anyone explain me why it's working with InputStream?

A M
  • 831
  • 1
  • 14
  • 26
  • 1
    I missed that in your code. `InputStreamReader` translates a call to `read()` into a buffered call since it needs to convert bytes to chars. For that you usually need more than one. Furthermore, buffered reading is much faster. So when you write `read()` it translates to `read(arrayOf8192Bytes)`. – Shai Almog Jun 13 '18 at 05:29