Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (580)
games submitted by our members
Games in WIP (500)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Socket Listener "dies" with time  (Read 1804 times)
0 Members and 1 Guest are viewing this topic.
Offline teletubo
« League of Dukes »

JGO Ninja


Medals: 48
Projects: 6
Exp: 8 years



« Posted 2011-11-10 17:51:22 »

I have a problem with the server of Reign of Rebels , that after a few days running, it simply stops accepting connections in an unusual way.

The client tries to connect, it gets no error at first. Instead, it takes 50 - 80 seconds or so for the client to get a connection error. As if the client were negotiating connection.
If server is down, the client gets the message immediatelly.

I believe there's something wrong my code, I'll post the code I use to accept/close connection and would appreciate if somebody sees something weird.

Accepting new connections. I start 10 Threads of these:
1  
2  
3  
4  
5  
6  
7  
8  
public void run() 
{
    while (true)
        {
       MMTCPConnection c = new MMTCPConnection(welcomeSocket, this);
       addConnection(c); /* this does not block, definetely*/
   }
}



this is in the constructor of MMTCPConnection :
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
Socket connectionSocket;
....
      try
      {
   connectionSocket = ss.accept();
   inFromClient = new DataInputStream(connectionSocket.getInputStream());      
   outToClient = new DataOutputStream( new BufferedOutputStream( connectionSocket.getOutputStream()));
        }catch (Exception e) {
         e.printStackTrace();
         try {
            connectionSocket.close();
         } catch (IOException e1) {
            e1.printStackTrace();
         }
      }




In the class MMTCPConnection, when any error occur (including client closed connection), I call this method :
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  
   Socket connectionSocket;
   DataOutputStream outToClient;
   DataInputStream inFromClient;

   private  void closeConnection()
   {
      server.connectionsV.remove(this.id);
      try
      {
         inFromClient.close();
      }
      catch (Exception e)
      {
         e.printStackTrace();
      }

      try
      {
         outToClient.close();
      }
      catch (Exception e)
      {
         e.printStackTrace();
      }

      inFromClient=null;
      outToClient=null;

      try {
         connectionSocket.close();
      } catch (IOException e) {
         e.printStackTrace();
      }

      System.out.println("closed connection . "+(int)id);

   }


Am I missing something ?


Offline Riven
« League of Dukes »

JGO Overlord


Medals: 605
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #1 - Posted 2011-11-10 18:16:03 »

You should only .accept() a socket in the thread that is listening for incoming connections. Once you obtain a socket, pass the reference to another thread and handle the socket there. Don't even request the steams, don't set the timeout, pass it off right away.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline teletubo
« League of Dukes »

JGO Ninja


Medals: 48
Projects: 6
Exp: 8 years



« Reply #2 - Posted 2011-11-10 19:23:07 »

If I understand correctly, then I should only start 1 Thread for accepting connections, and handle the starting of it in another thread ? Like :

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
ServerSocket welcomeSocket;
Socket connectionSocket ;
...

public void run()  /* only one Thread will be started */
{
    while (true)
        {
         connectionSocket = welcomeSocket.accept();
         createThreadToHandleNewConnection(connectionSocket);
   }
}

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline sproingie
« Reply #3 - Posted 2011-11-10 19:38:15 »

I'd create the thread from a pool or send the connection to a connection-handling actor (I'm a scala guy), but yeah that's basically the right idea: get it out of the accepting thread ASAP.

Offline Riven
« League of Dukes »

JGO Overlord


Medals: 605
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #4 - Posted 2011-11-10 21:56:16 »

1  
2  
3  
4  
5  
while (true) 
{
   final Socket socket = serversocket.accept();
   // pass it off
}
even this loop is not stable enough for a server under heavy load. It takes only 1 short burst of new connections (thousands) and you run out of file-descriptors, causing .accept(...) to throw an IOException, and your server is unreachable. forever.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
while (true) 
{
   try {
      final Socket socket = serversocket.accept();
      // pass it off
  }
   catch(IOException exc) {
       Thread.sleep(...); // cool down, maybe take action
  }
}
I found out the hard way.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline sproingie
« Reply #5 - Posted 2011-11-10 22:46:06 »

If you're spawning off new threads for connections, you should definitely use a thread pool in order to throttle bursts.  If you run out of threads in the pool, you can shunt the connection off to a "we're busy, try again" response (I call that kind of handler a "Snubber").  If you control the client, it's possible the user doesn't ever see an error, because you can make the client try again.  Certainly that's nicer than a connection refused error.

Thread-per-connection can scale pretty well these days with NPTL on Linux, but it's never going to scale as well as NIO, and you still have to stay vigilant about keeping thread growth under control.
Offline teletubo
« League of Dukes »

JGO Ninja


Medals: 48
Projects: 6
Exp: 8 years



« Reply #6 - Posted 2011-11-10 23:13:32 »

If you're spawning off new threads for connections, you should definitely use a thread pool in order to throttle bursts.  If you run out of threads in the pool, you can shunt the connection off to a "we're busy, try again" response (I call that kind of handler a "Snubber").  If you control the client, it's possible the user doesn't ever see an error, because you can make the client try again.  Certainly that's nicer than a connection refused error.

Thread-per-connection can scale pretty well these days with NPTL on Linux, but it's never going to scale as well as NIO, and you still have to stay vigilant about keeping thread growth under control.


I understand this concern, but right now I have like 2, maximum 3 non-simultaneous connections per day, and still that happens. I'm not thinking about scaling well, I just want it to work stable for a long time, which is not happening.

I'll change the server with suggestions given here, and increase logging to see exactly where my accpt thread stops responding.

Thank you for now.

Offline delt0r

JGO Coder


Medals: 22


Computers can do that?


« Reply #7 - Posted 2011-11-11 10:32:03 »

If you expect the thing to stay up 24/7 I would recommend catching exceptions like Riven suggested and just "resetting" the socket. That means closing and waiting a bit so the os is clear that the port is not already bound, try starting it again, rinse and repeat. On a server it pays to increase the max amount of file descriptors you have. 

Same goes for open connections. Sure you can get cases where a tcp connection won't go dark for days even weeks. But it is far more likely to get go dark on the order of hours.

I have no special talents. I am only passionately curious.--Albert Einstein
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

xsi3rr4x (52 views)
2014-04-15 18:08:23

BurntPizza (49 views)
2014-04-15 03:46:01

UprightPath (64 views)
2014-04-14 17:39:50

UprightPath (46 views)
2014-04-14 17:35:47

Porlus (63 views)
2014-04-14 15:48:38

tom_mai78101 (88 views)
2014-04-10 04:04:31

BurntPizza (147 views)
2014-04-08 23:06:04

tom_mai78101 (244 views)
2014-04-05 13:34:39

trollwarrior1 (203 views)
2014-04-04 12:06:45

CJLetsGame (210 views)
2014-04-01 02:16:10
List of Learning Resources
by SHC
2014-04-18 03:17:39

List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!