I am beginning the process of writing a network-enabled program for OS X using Cocoa and would like to hear your opinions on what would be the best approach to take.
I know about CFSocket, but would prefer to use non-blocking BSD sockets.
My problem is that I need to have a way to respond to user-interface events while at the same time checking to see if data arrives on the socket. This is typically done using a worker thread that, in my case, would use the select(...) function to determine if there is any data to be read from the socket. In this way, the worker thread is then woken up whenever the server sends data to the client. So far, so good.
However, let's suppose the user wants to send a file. This cannot be done in the main thread, as it would block. So we must instead use a worker thread to handling the transmission. Why not just use the other worker thread that is already waiting for data to arrive? Well, as it turns out, select will block until there is data, and we don't want to have to wait for data in order to start the upload. I know -- select can make use of a timeval struct, so it can time out, but then, you'd have the select call timeout after no data is available to be read, and then you'd have to check and see if the user actually issued a command that required sending data. If he or she did not, then the loop would continue, and eat up 100% CPU. Do you see the problem? How can I use just one thread to monitor for incoming data, and at the same time use it to send data based on an event received from the user?
I guess what I'm trying to do is emulate the asynchronous behavior that CFSocket would provide, but do so using BSD sockets.
I came up with an idea that would use not just one worker thread, but two. So you have one thread that is solely responsible for handling incoming data, and another that is responsible for taking the button click from a user and initiating a file upload, which would ordinarily block the main thread.
Does any of this sound reasonable? Am I not thinking of the "obvious" solution? I have spent many, many hours thinking about the best approach. It seems like in networking, there are so many wrong ways to design the software, and only one really good way, but finding the right approach really takes a lot of effort.
I think this idea would work... It's only downside is that it uses two threads to handle I/O on a socket, and lots of people complain that threads are nasty and should be avoided if at all possible. So, what do I do? I really want to use BSD sockets, but it almost seems impossible to get the kind of asynchronous behavior I need in order to accommodate the event-driven user interface.
Any ideas or suggestions are very much appreciated. Thanks.
I know about CFSocket, but would prefer to use non-blocking BSD sockets.
My problem is that I need to have a way to respond to user-interface events while at the same time checking to see if data arrives on the socket. This is typically done using a worker thread that, in my case, would use the select(...) function to determine if there is any data to be read from the socket. In this way, the worker thread is then woken up whenever the server sends data to the client. So far, so good.
However, let's suppose the user wants to send a file. This cannot be done in the main thread, as it would block. So we must instead use a worker thread to handling the transmission. Why not just use the other worker thread that is already waiting for data to arrive? Well, as it turns out, select will block until there is data, and we don't want to have to wait for data in order to start the upload. I know -- select can make use of a timeval struct, so it can time out, but then, you'd have the select call timeout after no data is available to be read, and then you'd have to check and see if the user actually issued a command that required sending data. If he or she did not, then the loop would continue, and eat up 100% CPU. Do you see the problem? How can I use just one thread to monitor for incoming data, and at the same time use it to send data based on an event received from the user?
I guess what I'm trying to do is emulate the asynchronous behavior that CFSocket would provide, but do so using BSD sockets.
I came up with an idea that would use not just one worker thread, but two. So you have one thread that is solely responsible for handling incoming data, and another that is responsible for taking the button click from a user and initiating a file upload, which would ordinarily block the main thread.
Does any of this sound reasonable? Am I not thinking of the "obvious" solution? I have spent many, many hours thinking about the best approach. It seems like in networking, there are so many wrong ways to design the software, and only one really good way, but finding the right approach really takes a lot of effort.
I think this idea would work... It's only downside is that it uses two threads to handle I/O on a socket, and lots of people complain that threads are nasty and should be avoided if at all possible. So, what do I do? I really want to use BSD sockets, but it almost seems impossible to get the kind of asynchronous behavior I need in order to accommodate the event-driven user interface.
Any ideas or suggestions are very much appreciated. Thanks.