Thread help

Started by
5 comments, last by hplus0603 19 years, 4 months ago
Hey, I need to make a simple client server CHAT project in c++. When a client is connecting to a server, the server oppens a new thread and begins the communication with the client using this thread. When a client sending a string (chat msg) the server receives it and sends it to all the clients connected. Now my questions is this: if all the clients connected to the server in threads. how can i tell each thread to send a msg. I understand that the thread is a single function. Can i make the thread be a whole class? So i can have Thread.ListenFunc() constantly running and when the server needs to send a msgs to all the threads I'll call Thread.send(msg) from the main func. is it posibble?
;)
Advertisement
I'm thinking of that you should build a collection of all client connections over threads. After that you may call "SendAll" function for sending message to all clients.
instead of creating a thread per client, it would be much more practical to just use asynchronous sockets over your main thread.
To answer the original question, what is the specific problem?

If you have a good sockets implementation, then you can write on a socket from one thread while blocking to read from another. However, not all sockets implementations support this. If that doesn't work for you, I would suggest using select() in a single thread. In fact, I would suggest single-threaded no matter what :-)

Here are the two approaches, in beautiful pseudo-code:

// multi-threaded implementationLockOfSomeSort gConnectionsLock;std::list< Connection > gConnections;// in each threadwhile( myConnected ) {  read( mySocket, intoBuffer );  // I read a message -- better send it to everybody.  // Because I'm threaded, I have to hold a lock, that   // everyone will hold when accessing gConnections, so   // there's no race between the list being modified.  gConnectionsLock.Lock();  std::for_each( gConnections.begin(), gConnections.end(), write( intoBuffer ) );  gonnectionsLock.Unlock();}


// single-threaded implementationstd::list< Connection > gConnections;while( true ) {  select( &ready );  // select() will have returned a bunch of read-to-read   // sockets. I'll read all the messages from those sockets   // into a list of messags to process.  std::list< Message > messages;  std::for_each( gConnections.begin(), gConnections.end(), readInto( messages ) );  // My "processing" of messages just means forwarding them   // to everybody.  std::for_each( messages.begin(), messages.end(), sendToAll( gConnections ) );}

enum Bool { True, False, FileNotFound };
Thanks guys :) But my instructor insists me to use threads per connection.
I got another idea, make a Session class which include:
* one thread function which will listen to the socket
* one socket to communicate with the client
* send function
* mutex for the socket

so when i need to use the session.send(msg) , the send func will compete with the session.listen() thread ,of this specific session, over the socket. This solves my problem i think.

When a client receives a msg, it will push it to the msg qeuee (which is global), and the server will alsways check if this qeuee is not empty, than it will send all the clients the msg : session.send(msgQ->pop());

Sounds ok?
;)
In practical situation, create thread for each client is not the best solution if you are ready for about hundreds connection. Since context switch should be considered as a large overhead of your server application when more threads created.
I think the biggest problem with threads is that you have to lock your shared world representation, so all the threads typically just end up serialized on that lock anyway -- gaining no useful parallelism.

For the original homework question, just stick 'em all in a list, wrap a lock around the list, and when you receive a message, grab the lock, loop over the list, and forward the message to each socket in the list. This assumes you have a non-broken sockets implementation -- if it's broken, you'll probably deadlock when doing this.
enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement