[Java] ServerSocket wordt onverwacht gesloten

Pagina: 1
Acties:

  • Robtimus
  • Registratie: November 2002
  • Laatst online: 15:28

Robtimus

me Robtimus no like you

Topicstarter
Ik ben eindelijk in de eerste testfase aanbeland van mijn project, maar ik loop opeens tegen een onverwachte fout aan, en ik zie niet waarom.

Ik heb een zgn Controller die connecties ontvangt, en deze dan doorgeeft aan een andere thread om het af te handelen. Alleen het probleem: zover komt hij niet eens. Al op de eerste ServerSocket.accept() krijg ik een SocketException met de melding "ServerSocket is closed".

De relevante code:

Controller:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public void run()
{
    try
    {
        server = new ServerSocket(port); // port is een private int field
        server.setSoTimeout(timeout); // timeout is een private int field
        if (Kernel.DEBUGGING) // als we aan het debuggen zijn
        {
            System.out.println("- Controller server socket created");
        }
    }
    catch (IOException e)
    {
        System.err.println("Error creating server socket.");
        return;
    }
    running = true; // private boolean field
    Socket socket = null; // de socket die het verder afhandelt.
    ObjectInputStream in = null; // inputstream van socket
    Action action = null; // klasse die overgestuurd wordt
    while (running)
    {
        waitForNextPeriod(); // javax.realtime method, voor periodieke executies
        try
        {
            try
            {
                socket = server.accept(); // <- hier gaat het fout!
                if (Kernel.DEBUGGING)
                {
                    System.out.println("- Controller got connection");
                }
            }
            catch (SocketTimeoutException e)
            {
                // timeout occurred, skip to next
                if (Kernel.DEBUGGING)
                {
                    System.out.println("- Controller: timeout");
                }
                continue;
            }
            in = new ObjectInputStream(socket.getInputStream());
            // the first action is a dummy action.
            action = (Action)in.readObject();
            if (Kernel.DEBUGGING)
            {
                System.out.println("- Controller: got first action: " +
                                   action);
            }
            // afhandeling van action
        }
        catch (IOException e)
        {
            System.err.println(e); // en deze komt dus tig keer voorbij
        }
        catch (ClassNotFoundException e)
        {
            System.err.println(e);
        }
    }
}
De verzendende kant:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
private static class ConnectionIO // class als encapsulatie van in en out, voor in een map
{
    public ObjectInputStream in;
    public ObjectOutputStream out;
    public ConnectionIO(ObjectInputStream in, ObjectOutputStream out)
    {
        this.in = in;
        this.out = out;
    }
}

private ConnectionIO getIO(Action action)
{
    // connections is een map van action naar io
    ConnectionIO io = (ConnectionIO)connections.get(action);
    if (io == null) // eerste keer, creeer de socket
    {
        try
        {
            Socket socket = new Socket("localhost", port);
            // hier bestaat socket wel!
            io = new ConnectionIO(
                new ObjectInputStream(socket.getInputStream()),
                new ObjectOutputStream(socket.getOutputStream())
            );
            connections.put(action, io);
            // write an initial dummy action
            io.out.writeObject(action);
        }
        catch (IOException e)
        {
            System.err.println(e);
        }
    }
    return io;
}

public Tuple read(Tuple template)
{
    Action action = new Action(Action.READ, template);
    ConnectionIO io = getIO(action); // in getIO krijgt de client een NullPointerConnection
                                     // op Socket.connect(SocketAddress, int)
    try
    {
        io.out.writeObject(action);
        /*
         * Wait for the return; since actions are periodic, it will occur
         * before a new equal action.
         */
        return (Tuple)io.in.readObject();
    }
    catch (IOException e)
    {
        System.err.println(e);
    }
    catch (ClassNotFoundException e)
    {
        // Should not occur, since the type will be the same as template.
        System.err.println(e);
    }
    return null;
}
De controller leest dus eerst een dummy action, gevolgd door de echte read action; write action. Dit doe ik om niet steeds weer voor 1 bericht een connectie te maken terwijl ik die periodiek nodig heb. Zover komt het alleen niet eens, want de allereerste getIO in de zendende kant gaat niet eens goed.

Ik zie het niet meer, iemand anders wel?

More than meets the eye
There is no I in TEAM... but there is ME
system specs


  • Feyd-Rautha
  • Registratie: November 2001
  • Laatst online: 02-08-2025
Print eens je stack af in je catch-clausules. Misschien kan dit je al heel wat verder helpen.

Ik zie eigenlijk geen fouten in uw code. Het enigste wat de oorzaak kan zijn denk ik , is die setSoTimeout().
Dus dat uw serverSocket de timeout bereikt heeft voordat hij iets ontvangen heeft van uw client. Misschien moet je dat eens op 0 zetten ofzo.

[ Voor 59% gewijzigd door Feyd-Rautha op 19-04-2004 15:45 ]

I must not fear. Fear is the mind-killer. Fear is the little-death that brings total obliteration. I will face my fear. I will permit it to pass over me and through me. Where the fear has gone there will be nothing. Only I will remain.


  • Robtimus
  • Registratie: November 2002
  • Laatst online: 15:28

Robtimus

me Robtimus no like you

Topicstarter
Feyd-Rautha schreef op 19 april 2004 @ 15:38:
Print eens je stack af in je catch-clausules. Misschien kan dit je al heel wat verder helpen.

Ik zie eigenlijk geen fouten in uw code. Het enigste wat de oorzaak kan zijn denk ik , is die setSoTimeout().
Dus dat uw serverSocket de timeout bereikt heeft voordat hij iets ontvangen heeft van uw client. Misschien moet je dat eens op 0 zetten ofzo.
Aan de timeout mag het niet liggen, want dan hoort hij een SocketTimeoutException te gooien, geen SocketException.
Net de timeout op 0 gezet, de fout blijft zich herhalen zoals verwacht.

De stacktrace:
java.net.SocketException: ServerSocket is closed
at java.net.ServerSocket.bind(java.net.SocketAddress, int) (/root/jRateSuite/jRate-gcc/lib/libgcj.so.4.0.0)
at java.net.ServerSocket.bind(java.net.SocketAddress) (/root/jRateSuite/jRate-gcc/lib/libgcj.so.4.0.0)
at rgspace.api.Controller.run() (Unknown Source) <- mijn klasse
at _Jv_ThreadRun(java.lang.Thread) (/root/jRateSuite/jRate-gcc/lib/libgcj.so.4.0.0)
at __clone (/lib/libc-2.3.2.so)

Dit komt omdat ik het compile met jRate-gcj, een realtime extensie op gcj. Ik heb het ook geprobeerd zonder jRate met de TimeSys JVM (die is gemaakt voor dit soort code), maar die doet het absoluut niet beter.

[ Voor 4% gewijzigd door Robtimus op 19-04-2004 16:14 ]

More than meets the eye
There is no I in TEAM... but there is ME
system specs


Verwijderd

Ik zie ook geen fouten in je code, maar goed, er moet toch wel wat fout (of in je code of één of ander gegeven klopt niet).


Van java.sun.com:
public class SocketException
extends IOException
Thrown to indicate that there is an error in the underlying protocol, such as a TCP error.

Since:
JDK1.0
See Also:
Serialized Form

Ik weet niet hoor, maar als het een TCP error is, dan wordt het toch lastig. Ik zou toch een aantal dingen gaan checken. Het serversocket wat explicieter openen en minder java zelf laten doen. Zoals je serversocket dmv deze constructor te maken:
ServerSocket(int port, int backlog, InetAddress bindAddr)

En wat checks uitvoeren, bijvoorbeeld wanneer het serversocket geopend is of niet (direct na het creeeren ff isClosed() er op los laten). Dan kan je misschien wat makkelijker de/een fout opsporen.

  • Robtimus
  • Registratie: November 2002
  • Laatst online: 15:28

Robtimus

me Robtimus no like you

Topicstarter
Ik ga dat expliciet openen maar eens proberen morgen, misschien dat jRate daar niet goed mee overweg kan.
Eerst maar eens de meest simpele test schrijven daarvoor.

More than meets the eye
There is no I in TEAM... but there is ME
system specs


  • Robtimus
  • Registratie: November 2002
  • Laatst online: 15:28

Robtimus

me Robtimus no like you

Topicstarter
Het ligt blijkbaar aan de compiler. Zelfs het creeren van een eenvoudige server socket (ServerSocket ss = new ServerSocket(9000);) vertikt hij te doen, ik krijg dan een IllegalArgumentException.

Ik moet dus op zoek naar een andere oplossing. Ik vraag me alleen af waarom ik die melding niet eerder kreeg; IllegalArgumentException vang ik nergens af.

More than meets the eye
There is no I in TEAM... but there is ME
system specs


Verwijderd

Probeer de code eens te compilen met de gewone Sun Java compiler als je dat nog niet had geprobeerd.

Verder kun je misschien proberen (als test) of je geen IllegalArgumentException krijgt als je gewoon 0 als poort opgeeft bij het creeren van de socket. Het wordt dan wel wat lastiger connecten naar de server, maar als het dan werkt ligt het gewoon aan je netwerk-instellingen/progsels.

  • Robtimus
  • Registratie: November 2002
  • Laatst online: 15:28

Robtimus

me Robtimus no like you

Topicstarter
Verwijderd schreef op 21 april 2004 @ 15:32:
Probeer de code eens te compilen met de gewone Sun Java compiler als je dat nog niet had geprobeerd.
Compilen gaat goed, maar wegens extensies in javax.realtime kan de JVM het niet runnen (link errors; missende libraries).
Verder kun je misschien proberen (als test) of je geen IllegalArgumentException krijgt als je gewoon 0 als poort opgeeft bij het creeren van de socket. Het wordt dan wel wat lastiger connecten naar de server, maar als het dan werkt ligt het gewoon aan je netwerk-instellingen/progsels.
Nog steeds die IllegalArgumentException. Dat ligt aan die compiler (jRate), want dezelfde code werkt wel in de TimeSys VM (die dus niet die libraries mist). Die gooit echter al een NoClassDefFoundError over java.net.SocketTimeoutException. Die is dus ook onbruikbaar in de huidige vorm.

More than meets the eye
There is no I in TEAM... but there is ME
system specs


  • Robtimus
  • Registratie: November 2002
  • Laatst online: 15:28

Robtimus

me Robtimus no like you

Topicstarter
Leuke ontdekking.

Net nog maar even de oorspronkelijke code geprobeerd met jRate, en het viel me op dat ik in debugging mode niet die "- Controller server socket created" melding kreeg. Na wat System.out.println's ben ik erachter gekomen dat hij blockt op setSoTimeout, waarom weet ik niet. Het probleem is alleen dat ik wel timeouts MOET gebruiken, gezien het geheel nogal tijdsafhankelijk is. 1 run moet binnen een bepaalde tijd afgelopen zijn, en met blocking op accept kun je dat niet garanderen. Die timeout statement verwijderen lost het probleem echter nog niet op.

Ook leuk is dat de isBound() en isClosed() methods niet worden ondersteund (zijn pas in 1.4 erbij gekomen).

Er is een nieuwere versie van jRate beschikbaar, gebaseerd op gcc 3.3.2 ipv 3.3.1. Ik zal die eens gebruiken, hopen dat dat werkt.

More than meets the eye
There is no I in TEAM... but there is ME
system specs

Pagina: 1