koraktor / steam-condenser

A multi-language library for querying the Steam Community, Source, GoldSrc servers and Steam master servers
https://koraktor.de/steam-condenser
Other
356 stars 67 forks source link

Android: SteamCondenserException on new SourceServer #269

Closed daparker closed 8 years ago

daparker commented 9 years ago

I'm working on a new version of CheckValve and I have run into a strange issue which I can't solve. I have the following code to instantiate a new SourceServer:

s = new SourceServer(InetAddress.getByName(rconServer), rconPort);

If this is the first time this code has run in the current session of the app, then it works fine. However, if this code has been run at least once before during this app session (for example, if the user was in an RCON session, then navigated back to the main screen, and then went back to RCON), then I get a SteamConsenserException from the QuerySocket constructor (QuerySocket.java):

protected QuerySocket(InetAddress ipAddress, int portNumber)
        throws  SteamCondenserException {
    super(ipAddress, portNumber);

    try {
        this.channel = DatagramChannel.open();
        this.channel.configureBlocking(false);
        ((DatagramChannel) this.channel).connect(this.remoteSocket);
    } catch(IOException e) {
        throw new SteamCondenserException(e.getMessage(), e);
    }

Specifically, the ((DatagramChannel) this.channel).connect(this.remoteSocket) call is throwing a java.nio.channels.ClosedByInterruptException, and that's the mystery. Do you know why that call to connect() would be throwing an exception, but only when an RCON session has been established to the server previously?

Thanks for any help or clarification you can provide.

koraktor commented 9 years ago

I'm not really into Android development, so I don't know how the OS limits and regulates socket connections.

Do you call #close after communication is finished? I guess this is safest way if you keep the objects around (while the app is running). This should avoid dangling connections.

daparker commented 9 years ago

Thanks for the reply. Yes, I was calling close() but it didn't have any effect on the issue, but I think I have resolved it now. I was creating the SourceServer instance on the main UI thread, which remains running during the entire lifetime of the app session. I moved the new SourceServer call to a background thread and the issue seems to be fixed. I'll do some more testing, but so far that seems to have been the culprit.

daparker commented 9 years ago

Actually, I was calling disconnect() on the SourceServer, not close(). Would that make a difference?

koraktor commented 9 years ago

Whoops, I meant disconnect(). It calls close() on the underlying sockets.

koraktor commented 8 years ago

Do you have any update on this? Maybe a full stack trace might help.

daparker commented 8 years ago

It seems to have been an issue with creating the SourceServer instance on the main UI thread in Android, and then performing socket operations on it. Creating the SourceServer in a background thread works perfectly. It's an Android-specific issue. Google made a change which disallows network operations on the main thread in the newer Android versions.

koraktor commented 8 years ago

Thanks for the clarification.