Jump to content
  • Advertisement
Sign in to follow this  
StrideKnight

C++ Thread safety, and a sockets question

This topic is 3813 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey guys, I've been trying to figure something out and I was hoping to get some feedback. I'm trying to write a simple chat server program in windows just because I wanted to learn more about threads/sockets. I was thinking of how to structure the server side and I figured I would have worker threads for each socket (chat client) that simply takes the users input (chat lines, /msgs, whatever) and puts it into a queue that the main thread would then pop from, and do whatever appropriate work. That way I can have synchronized chat input and whatnot. Now, where I hit the problem is that, are Queue's threadsafe? And if so/if not are there any containers that are? I would think a queue is because it doesn't directly operate like, say, an array or something, but I don't know the internals for a queue. I know I could use a mutex to lock the queue if I have to, but I was reading and it said that acquiring a lock was a rather intensive process? The other thing that worried me about using a mutex, and this is where my limited knowledge of sockets comes in to play, if I have a looping recv() to get input from a client socket and I have to pause the loop to acquire the mutex, but while the thread is waiting to acquire the mutex more data comes in from the socket, it will buffer it right? In which case it's not such a big deal about waiting for the mutex. However, will recv() return both consecutive inputs at once (like concatenated strings)? Or do I need to call it twice to get both inputs? Alright, I hope that makes sense. Thanks! -Dave

Share this post


Link to post
Share on other sites
Advertisement
I'll address some of your issues with my limited knowledge of threads and sockets.

1. If you use the TCP/IP protocol as opposed to UDP then the data is guaranteed to reach you. I'm not sure of the specifics but it's part of the underlying makeup of the protocol. As a consequence it can be slower which is why some games use UDP.

2. From my experience using mutex's hasn't been all the intensive (or difficult).

3. Since you intend to thread off each client anyway why do you add the network code to that thread as well? That way every time you get a connection you just thread it off into its own little world and let the thread be a self contained unit that receives and processes input. Just a thought.

Share this post


Link to post
Share on other sites
Quote:
Original post by atimes

1. If you use the TCP/IP protocol as opposed to UDP then the data is guaranteed to reach you.


No, it's not. But that data that does arrive will be valid and in same order. Boundaries between data sent are not preserved, so if you send several pieces of data, they may arrive in one single chunk.

Quote:
Now, where I hit the problem is that, are Queue's threadsafe?


What is a Queue? Which language, which implementation? Lock-less queue? Blocking queue?

Quote:
but while the thread is waiting to acquire the mutex more data comes in from the socket, it will buffer it right?


Network stack has a fixed buffer. Once it's full, incoming data is discarded. In case of UDP, this is lost permanently. In case of TCP, network stack will eventually determine it's missing some data, and will ask the peer to resend it.


Socket functions are re-entrant. Reading from same socket by multiple threads however doesn't make conceptual sense, and mutex here is absolutely worst choice. At best, you'll run at single-threaded rate, at worst, you'll have severe contention issues.


Sockets provide non-blocking operation via select, Windows provides IOCP and *nux provices epoll/aio/kqueue for high-performance networking. Non-blocking should be the first choice to look into, since a chat application is unlikely to have performance issues.

Share this post


Link to post
Share on other sites
Quote:
Original post by Antheus
... in same order. Boundaries between data sent are not preserved, so if you send several pieces of data, they may arrive in one single chunk.

You sure? It has been my experience that both of these statements are incorrect.

-- Edit --

Nevermind I misunderstood you were talking about TCP not UDP my bad.

Share this post


Link to post
Share on other sites
Quote:
C++ Thread safety

C++ does not acknowledge the existance of threads. Any use of threads immediately puts you into the realm of non-standard behavior. You'll need to consult the documentation of whatever library you're getting your queue object from to find out if, and under exactly what circumstances, it can be considered thread safe. If you mean std::queue, then I think both MSVC and gcc implementations are not thread safe. This tends to be the default.

Making things thread safe adds overhead even in non-threaded scenarios so locking, etc, gets pushed out so the programmer can do what they want rather than getting a certain policy thrust on them. It also makes the underlying code more portable.

Share this post


Link to post
Share on other sites
Quote:
Original post by StrideKnight

Now, where I hit the problem is that, are Queue's threadsafe? And if so/if not are there any containers that are? I would think a queue is because it doesn't directly operate like, say, an array or something, but I don't know the internals for a queue.

I know I could use a mutex to lock the queue if I have to, but I was reading and it said that acquiring a lock was a rather intensive process?

The other thing that worried me about using a mutex, and this is where my limited knowledge of sockets comes in to play, if I have a looping recv() to get input from a client socket and I have to pause the loop to acquire the mutex, but while the thread is waiting to acquire the mutex more data comes in from the socket, it will buffer it right? In which case it's not such a big deal about waiting for the mutex. However, will recv() return both consecutive inputs at once (like concatenated strings)? Or do I need to call it twice to get both inputs?

Alright, I hope that makes sense. Thanks!
-Dave


The standard lib's Deque is not thread safe you will need a lock. There are no locking primitives in the standard library. They are platform specific.

Locking is an expensive process not an intensive process. It is expensive in terms of computation time it is not expensive in terms of network time or how fast someone can type a message. So using a lock may effect scaling if you lock overly aggressively, or try to fine grain your locks too much.

TCP is a stream, how far you have received in the stream is what you get when you call revc. weather that is half a transmission or 40 transmissions. You need some way of determining both message start and message end.

Share this post


Link to post
Share on other sites
Quote:
Original post by Antheus
Socket functions are re-entrant. Reading from same socket by multiple threads however doesn't make conceptual sense, and mutex here is absolutely worst choice. At best, you'll run at single-threaded rate, at worst, you'll have severe contention issues.

Sockets provide non-blocking operation via select, Windows provides IOCP and *nux provices epoll/aio/kqueue for high-performance networking. Non-blocking should be the first choice to look into, since a chat application is unlikely to have performance issues.


Hmmm, I'm not sure I explained myself clearly. Sorry, When I try and word a problem I have a tendency to ramble.

Basically, my thought is that I have my main thread, which will just sit there and listen for connections. When it accepts a socket, the socket will be passed to some handling function that will be spawned off as a new thread. So I don't have multiple threads accessing the same socket, rather, I have one thread per socket connection.

What I wanted them to be able to do was then pass information back to the parent, main, thread. That's where I was going with the whole thread-safe container idea. So in this case would a mutex be a bad idea? And I assume it's better in general to use select() than multiple threads, correct?

Thanks!

Share this post


Link to post
Share on other sites
Quote:
Original post by stonemetal
The standard lib's Deque is not thread safe you will need a lock. There are no locking primitives in the standard library. They are platform specific.


I should've figured since all the other threading stuff is. Thanks.

Quote:
Locking is an expensive process not an intensive process. It is expensive in terms of computation time it is not expensive in terms of network time or how fast someone can type a message. So using a lock may effect scaling if you lock overly aggressively, or try to fine grain your locks too much.


I don't suppose that's one of those quantifiable things right? More, a if you notice it, fix it, kind of thing right?

Quote:
TCP is a stream, how far you have received in the stream is what you get when you call revc. weather that is half a transmission or 40 transmissions. You need some way of determining both message start and message end.


Ahhhh, I see. Is there some kind of convention or common method used? Seems like this is where security loopholes could come from, right? Like if all I use to start and end a message is <start>/<end> then execute whatever commands inbetween all someone would have to do is to figure out that syntax and then I'm screwed huh.

Share this post


Link to post
Share on other sites
Quote:
Original post by StrideKnight
Quote:
Original post by stonemetal
The standard lib's Deque is not thread safe you will need a lock. There are no locking primitives in the standard library. They are platform specific.


I should've figured since all the other threading stuff is. Thanks.

Quote:
Locking is an expensive process not an intensive process. It is expensive in terms of computation time it is not expensive in terms of network time or how fast someone can type a message. So using a lock may effect scaling if you lock overly aggressively, or try to fine grain your locks too much.


I don't suppose that's one of those quantifiable things right? More, a if you notice it, fix it, kind of thing right?

Quote:
TCP is a stream, how far you have received in the stream is what you get when you call revc. weather that is half a transmission or 40 transmissions. You need some way of determining both message start and message end.


Ahhhh, I see. Is there some kind of convention or common method used? Seems like this is where security loopholes could come from, right? Like if all I use to start and end a message is <start>/<end> then execute whatever commands inbetween all someone would have to do is to figure out that syntax and then I'm screwed huh.
Don't waste your time thinking about what your protocol looks like to curious eyes. Security loopholes don't come from someone spying on your packets (unless you are guilty of Security through Obscurity, which is already bad) but from problems with your code. Spend your time making sure that your program isn't doing anything stupid (e.g. reading more data than it has room for, creating a buffer overflow).

The only "security" that you should have to deal with in your protocol, is the security of sensitive data (usernames, passwords, credit card numbers, etc). For that, you can use something like SSL.

Links:
- Security through obscurity: http://en.wikipedia.org/wiki/Security_through_obscurity
- SSL: http://en.wikipedia.org/wiki/Secure_Sockets_Layer

Share this post


Link to post
Share on other sites
Quote:
Original post by StrideKnight

I don't suppose that's one of those quantifiable things right? More, a if you notice it, fix it, kind of thing right?


Ahhhh, I see. Is there some kind of convention or common method used? Seems like this is where security loopholes could come from, right? Like if all I use to start and end a message is <start>/<end> then execute whatever commands inbetween all someone would have to do is to figure out that syntax and then I'm screwed huh.


It depends on your definition of screwed. If you distribute your app you are screwed since I can load up an app and modify your app's memory directly so I never have to know your protocol, I have hacked your app so it will speak the right protocol for me.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!