Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (513)
Games in Android Showcase (120)
games submitted by our members
Games in WIP (577)
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  
  Converting from TCP to UDP - Threading Clients?  (Read 1731 times)
0 Members and 1 Guest are viewing this topic.
Offline Chumble

Senior Newbie


Exp: 1 year



« Posted 2014-07-24 19:54:12 »

After many headaches, I have decided it is in my best interest to convert my client/server game to UDP from TCP. I am not interested in starting any TCP vs UDP discussion in this thread.


Currently, the setup is as follows (simplified)

Client
* Attempts connection to server. If success...
   * Creates a thread to listen for messages from server.
   * Processes client input, sends messages from server, interprets server response.

Server
* Waits for connection attempts. If a connection happens ...
   * Create a thread to listen for messages from client.
* Processes server input, sends messages to client, interprets client messages.

Pretty much the same on both sides except that there will be multiple threads generated by the server, one for each client.

I am having a fairly difficult time finding useful UDP examples to reference. I was using http://systembash.com/content/a-simple-java-udp-server-and-udp-client/ as a reference, but one main concern comes to mind.

Right now, when the server gets an incoming connection from a client, I create a new Socket for that client and pass it to the listen thread. With this UDP example, it seems to just accept any traffic over a given port .. so all of my traffic would go towards a single DatagramSocket.receive running on the main server. I guess I can get the IP address from the message in order to determine what player it belongs to but it really makes the whole thread part useless if all the messages will come to the same exact place. Am I correct in thinking this way?

Possible UDP setup?:

Client
 * Attempt to communicate with server. If successful...
   * Creates a thread to listen for messages from server.
   * Processes client input, sends messages from server, interprets server response.

Server
 * Create Main listen thread
   * Main Listen thread gets ALL messages from ALL clients. As soon as a message comes in, it determines which client it belongs to and hands the message off to a client-specific thread (or creates one if this is the client's first time connecting)
      * Client Listen thread processes the message and passes the response back to the client.
 * Processes server input, sends messages to client, interprets client messages.
Offline tkausl
« Reply #1 - Posted 2014-07-24 20:16:24 »

Right now, when the server gets an incoming connection from a client, I create a new Socket for that client and pass it to the listen thread. With this UDP example, it seems to just accept any traffic over a given port .. so all of my traffic would go towards a single DatagramSocket.receive running on the main server. I guess I can get the IP address from the message in order to determine what player it belongs to but it really makes the whole thread part useless if all the messages will come to the same exact place. Am I correct in thinking this way?
Yep, you are.

Possible UDP setup?:

Client
 * Attempt to communicate with server. If successful...
   * Creates a thread to listen for messages from server.
   * Processes client input, sends messages from server, interprets server response.

Server
 * Create Main listen thread
   * Main Listen thread gets ALL messages from ALL clients. As soon as a message comes in, it determines which client it belongs to and hands the message off to a client-specific thread (or creates one if this is the client's first time connecting)
      * Client Listen thread processes the message and passes the response back to the client.
 * Processes server input, sends messages to client, interprets client messages.
Well you could do this yourself this way but i think youre in better shape by using a Networking-lib. I think nettys udp works (for the programmer) almost the same way as tcp since netty creates "fake"-connections and handles the delegating (to which session/connection this packet belongs) itself.

My English isnt that great. Correct me, if you want, im still learning this Language Smiley
Offline Chumble

Senior Newbie


Exp: 1 year



« Reply #2 - Posted 2014-07-24 20:25:22 »

Thanks for the reply. I'll have to look up this "Nettys", I'm sure there's a few threads around here.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Herjan
« Reply #3 - Posted 2014-07-25 10:23:48 »

Possible UDP setup?:

Client
 * Attempt to communicate with server. If successful...
   * Creates a thread to listen for messages from server.
   * Processes client input, sends messages from server, interprets server response.

Server
 * Create Main listen thread
   * Main Listen thread gets ALL messages from ALL clients. As soon as a message comes in, it determines which client it belongs to and hands the message off to a client-specific thread (or creates one if this is the client's first time connecting)
      * Client Listen thread processes the message and passes the response back to the client.
 * Processes server input, sends messages to client, interprets client messages.

This is exactly how you should do this, I see you have already digged into this stuff (which is why I reply).
You should ignore tkausl's suggestion because I see no reason why you shouldn't do this yourself, if you want to keep it fast and organized at least...

Here is how I did it in my previous game:
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  
   public Runnable receiver = new Runnable(){
      byte[] receiveData = new byte[1024];
      int id = 0; // until we have connection to database use this temporary!!!!
     
      public void run(){
         while(running){
            total:
            try {
               DatagramPacket datagramPacket = new DatagramPacket(receiveData, receiveData.length);
               server.receive(datagramPacket);
               for(Client c : clients){
                  if(c.dp.getSocketAddress().equals(datagramPacket.getSocketAddress())){
                     c.handleMsg(datagramPacket.getData());
                     break total;
                  }
               }
               clients.add(new Client(datagramPacket, id++));
            } catch (Exception e) {
               e.printStackTrace();
            }
         }
         
         server.close();
      }
   };


I also have very nice code which handles the packet loss and eventual delivers them in order (and in incredibly quick Smiley ), if you would like to have them, you know where to find me.

Offline Chumble

Senior Newbie


Exp: 1 year



« Reply #4 - Posted 2014-07-25 13:08:50 »

Hi Herjan,

I actually tried implementing this last night (manually, not with Nettys) and it looks incredibly similar to what you posted above. So far my trouble is in converting the object I've been using for TCP network messages to a byte[] to use in UDP network transfer. I'm still playing with it and it's rather messy. I feel like I'm passing data around much more in this setup. Do you keep the send and receive code for UDP in the same place?

As far as packet loss, I think I'd like to take a thwack at that myself before looking for help. Looks like it might be kinda fun Smiley

Thanks,
Chumble
Offline Herjan
« Reply #5 - Posted 2014-07-25 15:26:59 »

As far as packet loss, I think I'd like to take a thwack at that myself before looking for help. Looks like it might be kinda fun Smiley

Haha, that's the spirit! And heck you will learn a lot thanks to that spirit Cheesy

And about the sending of packets, actually, in the same class, I had this function:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
public void write(DatagramPacket dp, int pckg, String[] parts) {
      String msg = "" + pckg;
      for(int i = 0; i < parts.length; i++)
         msg += PackageHandler.separator + parts[i];
     
      msg += PackageHandler.endPackage;
      dp.setData(msg.getBytes());
     
      try {
         sender.send(dp);
      } catch (IOException e) {
         e.printStackTrace();
      }
   }


int pckg, tells the server/client what to do with this data:
  • a login
  • input
  • or whatever

Offline Chumble

Senior Newbie


Exp: 1 year



« Reply #6 - Posted 2014-07-25 21:24:41 »

Ok, so I think I have the basics pretty well set up. It works with multiple clients locally. However, when I switch over to my external IP address to test it with a friend, the server gets the "Connection" request but the client never gets a response. This comes down to port forwarding, I believe.


On my router, I have forwarded the port that is used for the server when setting up the socket.
Server: socket = new DatagramSocket(54532);

On the client, I don't have anything forwarded.. I just have a port obtained automatically
Client: socket = new DatagramSocket();


So it appears to me that the client sends data to the server (me) via port 54532 and since it's forwarded, it works fine. But when the server replies to the client (getting the port with a Packet.getPort() ), the client doesn't get it. I feel like if I happened to have that port forwarded, it would work fine.. but I also feel like I shouldn't have to.


In my experience with online games, I've only had to forward ports when I am hosting a server, never when joining a game. I guess this comes down to a lack of understanding on how the networking works.. but it also might be bad code.

Do I need to establish a specific port for the client to listen to the server? If so, will I need it to be forwarded (and, less importantly, why)? And finally, will this prevent me from running multiple clients on MY pc since it will attempt to bind the same port multiple times?

Offline Herjan
« Reply #7 - Posted 2014-07-26 19:26:28 »

Do I need to establish a specific port for the client to listen to the server?

The answer: No, you should not.

If the client doesn't receive any messages, it's because you are doing something wrong in the server or (probably) client, you are probably using more than one datagramsocket in your client? (which you should not)

Offline Chumble

Senior Newbie


Exp: 1 year



« Reply #8 - Posted 2014-07-26 20:19:56 »

you are probably using more than one datagramsocket in your client? (which you should not)

I am not. I make sure that "New DatagramSocket" only appears in the client once and in the server once.
Pages: [1]
  ignore  |  Print  
 
 

 

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

The first screenshot will be displayed as a thumbnail.

Longarmx (52 views)
2014-10-17 03:59:02

Norakomi (43 views)
2014-10-16 15:22:06

Norakomi (33 views)
2014-10-16 15:20:20

lcass (37 views)
2014-10-15 16:18:58

TehJavaDev (68 views)
2014-10-14 00:39:48

TehJavaDev (66 views)
2014-10-14 00:35:47

TehJavaDev (59 views)
2014-10-14 00:32:37

BurntPizza (73 views)
2014-10-11 23:24:42

BurntPizza (45 views)
2014-10-11 23:10:45

BurntPizza (85 views)
2014-10-11 22:30:10
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
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!