Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: Multithreading & UDP Socket Programming

I am new to multithreading & socket programming in Java. I would like to know what is the best way to implement 2 threads - one for receiving a socket and one for sending a socket. If what I am trying to do sounds absurd, pls let me know why! The code is largely inspired from Sun's tutorials online.I want to use Multicast sockets so that I can work with a multicast group.

class Server extends Thread
{

    static protected MulticastSocket socket = null;
    protected BufferedReader in = null;
    public InetAddress group;

    private static class Receive implements Runnable
    {

        public void run()
        {
            try
            {
                byte[] buf = new byte[256];
                DatagramPacket pkt = new DatagramPacket(buf,buf.length);
                socket.receive(pkt);
                String received = new String(pkt.getData(),0,pkt.getLength());
                System.out.println("From server@" + received);          
                Thread.sleep(1000);
            }
            catch (IOException e)
            { 
                System.out.println("Error:"+e);
            }   
            catch (InterruptedException e)
            { 
                System.out.println("Error:"+e);
            }   

        }

    }


    public Server() throws IOException
    {
        super("server");
        socket = new MulticastSocket(4446);
        group = InetAddress.getByName("239.231.12.3");
        socket.joinGroup(group);
    }

    public void run()
    {

        while(1>0)
        {   
            try
            {
                byte[] buf = new byte[256];
                DatagramPacket pkt = new DatagramPacket(buf,buf.length);        
                //String msg = reader.readLine();
                String pid = ManagementFactory.getRuntimeMXBean().getName();
                buf = pid.getBytes();
                pkt = new DatagramPacket(buf,buf.length,group,4446);
                socket.send(pkt);
                Thread t = new Thread(new Receive());
                t.start();

                while(t.isAlive())
                { 
                    t.join(1000);
                }
                sleep(1);
            }
            catch (IOException e)
            { 
                System.out.println("Error:"+e);
            }   
            catch (InterruptedException e)
            { 
                System.out.println("Error:"+e);
            }   

        }
        //socket.close();
    }

    public static void main(String[] args) throws IOException
    {
        new Server().start();
        //System.out.println("Hello");
    }

}
like image 894
Ravi Avatar asked Dec 18 '22 01:12

Ravi


1 Answers

First thing is first: your classes should start with a capital letter per the Java Naming Conventions:

Class names should be nouns, in mixed case with the first letter of each internal word capitalized. Try to keep your class names simple and descriptive. Use whole words-avoid acronyms and abbreviations (unless the abbreviation is much more widely used than the long form, such as URL or HTML).

Second: Try to break down the code into coherent sections and organize them around some common feature that you're dealing with... perhaps around the functionality or the model you're programming.

The (basic) model for the server is that the only thing it does is receive socket connections... the server relies on a handler to handle those connections and that's it. If you try to build that model it would look something like this:

class Server{
    private final ServerSocket serverSocket;
    private final ExecutorService pool;

    public Server(int port, int poolSize) throws IOException {
      serverSocket = new ServerSocket(port);
      pool = Executors.newFixedThreadPool(poolSize);
    }

    public void serve() {
      try {
        while(true) {
          pool.execute(new Handler(serverSocket.accept()));
        }
      } catch (IOException ex) {
        pool.shutdown();
      }
    }
  }

  class Handler implements Runnable {
    private final Socket socket;
    Handler(Socket socket) { this.socket = socket; }
    public void run() {
      // receive the datagram packets
    }
 }

Third: I would recommend that you look at some existing examples.

  • Multi-threaded Client/Server Applications:
    http://www.ase.md/~aursu/ClientServerThreads.html
  • Doug Lea:
    http://www.developer.com/java/ent/article.php/3645111/Java-5s-BlockingQueue.htm (thanks to John)
    http://gee.cs.oswego.edu/dl/cpj/index.html (still can't find the exact example, but it's there somewhere... if you feel brave look over his allcode.java file).
  • Concurrency in Practice examples:
    http://www.javaconcurrencyinpractice.com/listings.html
  • Java Concurrency Tutorials:
    http://java.sun.com/docs/books/tutorial/essential/concurrency/

Updated per comments:
OK Ravi, there are some big issues with your code and some minor issues with it:

  1. I assume that the Receive class is your client... you should pull that out as a separate program (with its own main class) and run your server and multiple clients at the same time. Spawning a new "client thread" from your server for every new UDP package you send is a disturbing idea (big issue).

  2. When you make your client application, you should make it run the receiving code in its own while loop (minor issue), e.g.:

    public class Client extends Thread
    {
        public Client(/*..*/)
        {
            // initialize your client
        }
    
        public void run()
        {
            while(true)
            {
                // receive UDP packets
                // process the UDP packets
            }
        }
    
        public static void main(String[] args) throws IOException
        {
            // start your client
            new Client().start();
        }
    }
    
  3. You should only need just one thread per client and one thread per server (you technically don't even a separate thread in there since main has its own thread), so you might not find the ExecutorService that useful.

Otherwise your approach is correct... but I would still recommend that you check out some of examples.

like image 164
user2687585 Avatar answered Dec 21 '22 10:12

user2687585