CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 3 of 3
  1. #1
    Join Date
    Apr 2010
    Posts
    1

    Socket programming question.

    I'm trying to make an IM server/client, and I'm planning on using sockets. I got a nice little multi-client echo server up and running just fine, but I'm confused on how I should implement multiple users interacting with each other.

    I followed these few tutorials: http://java.sun.com/docs/books/tutor...ets/index.html

    And did what they did at the end with the multiple connections. Each connection is in its own thread. This works fine for a simple echo server, but how should I make each connection talk to each other?

    What I kind of was thinking, was having a class with a string for a users name. This class would hold almost everything for the user, and could be the thread that each connection is running through. But if it was like, I would need to be able to have one thread poke itself up and out into the main class, find the other thread with the name of the IM it is sending a message to, then jump into that thread and send a message.

    My idea seems like it would work, but I'm lost on how I would jump out of the current thread and find another thread to jump into. Could anyone give me some ideas here? The socket tutorial that I linked to wasn't very helpful in this aspect

  2. #2
    Join Date
    Apr 2007
    Posts
    442

    Re: Socket programming question.

    After all, there is really no reason to use a separate thread for each client. In most cases it is waste of resource. Instead you get as well away with an object, that holds a list of accepted sockets, runs through them, if any has something to read, reads the message, passes it on to some sort of protocol handling. Protocol handling returns a Message -object known to your system.

    Message is processed by Session management, which finds the user / users relevant to the message, and pools the message for sending to them.

    This approach leaves you room to develop new ideas, what about private rooms, topic based chats, whispers, group whispers, system related messages etc. Protocol can grow easily and session managing can be streched to accomodate various different approaches.

    Sounds perhaps a bit more complicated than it should be, let me break it down:

    - Reading
    Reads any incoming data from accepted sockets. If socket is dead, discards it. Any data red is passed on to protocol handling. This one is a separate thread. This way you get away with reading the sockets, with minimal fuss.

    -Protocol handling
    Protocol handling determines, if the message content can be understood by your system. If not, it parses a relevant error message. You need this sort of centralized message translator, since any system, even chat, ends up having more complex messaging over time. Protocol handling produces a system relevant Message -object.

    -Session Management
    Session management has understanding of which users are currently accepted into the system. When Message -object is passed to session management, it determines to whom it should be sent. Each session included in session manager might have a list of messages for sending. Session managers usually independently kick out any sessions idle for more than a set grace period. For checking of that, you need a daemon thread.

    -Outwriting

    Goes through sessions in session manager, if any session has messages that need to be sent, sends one, keeps on going. This is a separate thread.


    On the other hand, if you want to continue with using separate threads, have a list containing, say... SocketThread objects, each socketThread has a socket, handles the reading and the writing, and contains the username of the chatter, or what ever you choose to use as an identifier. Go through the the list, upon finding the correct user, have the socketThread send the message. However, pretty soon you will notice that in an approach where you aim to do all things in one basket, walls are pretty close.
    Last edited by Londbrok; April 23rd, 2010 at 12:56 AM.

  3. #3
    Join Date
    Feb 2008
    Posts
    966

    Re: Socket programming question.

    I think that using threading with a nested inner class would be a great polymorphic way to handles a system like this. Take this example:

    Code:
    public class Server {
        private ServerSocket server;
        private static final int PORT = 10649;
        protected static int numClients = 0;
        ArrayList<ConnectionHandler> connections;
        public Server() {
            try {
                server = new ServerSocket(Server.PORT);
                connections = new ArrayList<ConnectionHandler>();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        public void handleConnection() {
            System.out.println("Waiting for client to connect...");
            while (true) {
                try {
                    Socket socket = server.accept();
                    Server.numClients++;
                    ConnectionHandler ch = new ConnectionHandler(socket);
                    connections.add(ch);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        
        protected synchronized void messageFromClient(int message) {
              //From here you can display the message sent from the client to the screen
        }
    
        public static void main(String[] args) {
            Server s = new Server();
            s.handleConnection();
        }
        
        /**
         * Private inner class.  This class is used to read in the message
         * sent from the client and send a response message back to the 
         * client.
         */
        class ConnectionHandler implements Runnable {
            private Socket socket;
            private int clientNumer;
            
            public ConnectionHandler(Socket socket) {
                this.socket = socket;
                clientNumer = Server.numClients;
                
                Thread t = new Thread(this);
                t.start();
            }
             
            public void run() {
                ObjectInputStream ois = null;
                ObjectOutputStream oos = null;
                try
                {
                    while(true) {
                       ois = new ObjectInputStream(socket.getInputStream());
                       oos = new ObjectOutputStream(socket.getOutputStream());
                    
                       int message = (Integer) ois.readObject();
                       //if message is -1, end connection
                       if(message == -1) break;
                       
                       //call this method to display the message from the client
                       messageFromClient(message);
                       
                       // or you can send a response information to the client application
                       oos.writeObject("Unrecognized message.");
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        ois.close();
                        oos.close();
                        socket.close();
                   } catch(Exception e) { e.printStackTrace(); }
                }
            }
        }
    }
    This is just a little example that I saw a while back (and modified it a bit towards your needs). It illustrates though how you can have a nested inner class (each a single thread) that monitors for incoming messages and it can call a method of the parent class when it gets messages. From there notifications can be sent out to all other clients connected since you have a reference to all open connections in the ArrayList, or you can simply display the message from the client.

    You could have one thread monitoring for incoming connections by calling the handleConnections() method, and another thread that performs actions of each client (call the class client instead of Server). Make the ArrayList static so your thread has access to the instance that holds all of the connections created by the handleConnection() method.

    This obviously isn't a fully functional, complete example of what you need, I just wanted to show how it "could" be done using threading. I don't believe that using threads to handle this is such a bad thing.

    If you look at the call to the ObjectInputStream's readObject() method, if nothing is available then nothing will happen and that thread will go to sleep. The "overhead" is minimal in this case, the class is small, few instance variables, and it handles all of the synchronization and scheduling for you. With this technique you do not have to iterate through the list of connections every second to see if any have a message for you. That, to me, would be a bad idea.
    Last edited by ProgramThis; April 23rd, 2010 at 11:41 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured