Hot questions for Using Transmission Control Protocol in network programming

Question:

First off I'd like to apologize for any dumb questions, I'm still learning network programming.

I never did much network programming, other than out of self interest, and I only used Java's Socket and ServerSocket classes. With these classes, the paradigms I used were to have a single Java thread on the server side which accepted connections from clients, and then passed that accepted Socket onto its own Thread. Thus with 100 concurrent clients, there would be (potentially) 100 threads. Then the client and server could talk to each other on their own threads, separate from the other components of the system.

Now enter the DatagramSocket... I'm just learning about TCP vs UDP, so just discovered this class. It makes sense... you listen for packets on a port, and send packets on a port/address. The body contains a certain number of bytes and is optional (Still learning what the max body sizes are and such). From the information online, I've gathered that the socket listens for ANY packets on that port, and derives the source from the packet headers.

This is all good and fine, and I am comfortable with forwarding those packets to their own runnables in a pool, or their own threads, etc. What is bothering me though is that with TCP sockets, each Thread (One of the 100 in the above example) received only messages from the appropriate source. With Datagram sockets, all packets from every client is going to a single thread... and that thread is responsible for divvying the work.

How would something like that work in an MMO game... say you have a game server supporting 5000 players, and each player sends 15 packets per second... That's 75,000 packets per second, which seems heavy for a single thread to handle. (As opposed to 5000 threads which could each have 15 per second). Obviously that one thread could forward the packets to the proper places based on packet headers and a client hashmap, but I'm just uncomfortable that the listener thread itself is doing that logic.

Now it's possible that TCP is doing something similar (Some packet listener thread that forwards the data to the appropriate Socket), so really I'm losing nothing. I guess the root question boils down to... Is it possible to have multiple Server threads listening to the same port? For example, I'm picturing a load balancer which round robins the packets to different DataGramSocket listeners (One on each thread, maybe 3-4 threads). Then those listeners can do the job of the original single thread, which is sending those unordered packets to the correct locations in the program (Example, this packet came from 123.456.789.123 on port 6750... lets check our clientMap for where this should go... Okay, send to that threads packet queue).

I'm guessing the answer is that as long as the thread handling all the client packets is very lightweight (Just receive packet, delegate, repeat), then there is no problem even for high volume traffic.

Thanks!

EDIT: After some thought and Am_I_Helpful's comment (And now Jamal H), I realized you can abstract this out on a machine or port level. So if you have 3000 players, you could have a load balancer of sorts which directs that player to a particular machine or even a particular port on the machine. So that way you could have X number of server threads each listening for packets on a different port. Player 1 may hit port 7712, player 2 may hit 7713.


Answer:

First of all, if you don't have access to a large team of people, you wouldn't be writing all the network code from scratch for an MMO. You would use some sort of networking framework that handles load balancing and threading for you (Netty is a good one for Java)

For an MMO you would use Non Blocking IO (NIO), which does not map out each client's request to its own thread, but instead has a set number of threads it wants to use (determined by number of cores), and handles it like that

Regarding loading every request on a single thread, there are a couple of options. This is the reason why MMOs have multiple servers, each for a different area in a game. The central server would give the player the IP and port of the area server that he is currently in. You can also have multiple ports accepting on a single server if the server is powerful, and just send different players different ports to send to if you wanted to balance the load across multiple threads

Question:

I am trying to make a simple TCP chat program, and I want the user to be able to start the program, then be able to enter a specific ip to connect to, and then disconnect from that specific server, and then connect to another after that.

I know that the client is connected once it runs client.connect(timeout, ip, port), but the only way I know of to disconnect the client from the server is by exiting the program.

Is there any way to do this?


Answer:

You can use client.stop(); to disconnect

Question:

I've been trying to write a client process that will communicate with a serve.

I used the same code below but instead of scanner i used BufferedReader and the client input was a string. Furthermore, the server just changes the string to uppercase and sends it back to the client to be displayed on the screen. It worked.

However, when i changed the code so that the client can enter a double number [(ex: 1.6) the server should round it and send it back so that it'll be printed on the screen], i get no response.

And i got this error:

run:
Exception in thread "main" java.util.InputMismatchException
    at java.util.Scanner.throwFor(Scanner.java:864)
    at java.util.Scanner.next(Scanner.java:1485)
    at java.util.Scanner.nextDouble(Scanner.java:2413)
    at socketserver.SocketServer.main(SocketServer.java:38)
Java Result: 1

notes:

  1. I am using NetBeans.
  2. I used Scanner instead of using BufferedReader so that i'll be able to read a double number.

Client class

package socketclient;

import java.io.*; 
import java.net.*; 
import java.util.Scanner;


public class SocketClient {

    /**
     * @param args the command line arguments
     */
   public static void main(String args[]) throws Exception 
    { 
        double inputDouble; 
        double modifiedNum; 

        Scanner inFromUser = new Scanner(System.in);


        Socket clientSocket = new Socket("localhost", 6789); 

        DataOutputStream outToServer = 
          new DataOutputStream(clientSocket.getOutputStream());


          Scanner inFromServer = new Scanner(clientSocket.getInputStream());


        inputDouble = inFromUser.nextDouble(); 

        outToServer.writeDouble(inputDouble);


        modifiedNum = inFromServer.nextDouble(); 

        System.out.println("FROM SERVER: " + modifiedNum); 

        outToServer.close(); 
        clientSocket.close();

    } 

}

Server class

package socketserver;

import java.io.*; 
import java.net.*; 
import java.util.Scanner;


public class SocketServer {

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) throws Exception 
    { 
      double clientNum; 
      double roundedNum;

      ServerSocket welcomeSocket = new ServerSocket(6789); 

      while(true) { 

            Socket connectionSocket = welcomeSocket.accept(); 

            Scanner inFromClient = new Scanner(connectionSocket.getInputStream());


            DataOutputStream  outToClient = 
             new DataOutputStream(connectionSocket.getOutputStream()); 

           clientNum = inFromClient.nextDouble(); 


           roundedNum= Math.round(clientNum);


           outToClient.writeDouble(roundedNum); 
        } 
    } 


}

Answer:

Your error is to use Scanner to read data sent by client from the server and the converse.

You use DataOutputStream to sent a double so you need a DataInputStream to read the double; on both sides.

Change your Scanners to DataInputStream for inputFromServer and inputFromClient. Also don't forget to flush your outputs and close the streams at the end.