.NET Forum / Languages / C# / March 2008
writing an async client (sockets/async/thread)
|
|
Thread rating:  |
asharda@woh.rr.com - 12 Feb 2008 20:04 GMT Hello,
My experience with socket-programming is close to zero.
I am looking for some kind of template which describes as to how the async-client (which can handle multiple responses from a server) can be written (i saw few examples on the net, but in those examples, the client execution terminates after sending/receiving response).
Basically, the client should: - Connect to the server (at specific IP/port) - Respond to any message it gets from server (once connected to the server, client should be continuously running, waiting for messages and and call respond appropriately).
So, this way, if there are multiple messages that server is sending to client at the same time, client should be able to handle it (so this client will be kind-of behaving like a server in the sense that each time it gets a connection, it assigns it to a worker-process and then keeps listening for other messages).
Is this feasible? if yes, then can you give some examples?
Platform: XP, vs2005 OR vs2008
Thanks.
Peter Duniho - 12 Feb 2008 20:38 GMT > Hello, > [quoted text clipped - 4 lines] > be written (i saw few examples on the net, but in those examples, the > client execution terminates after sending/receiving response). The difference between an application that terminates after sending and receiving a response and one that doesn't is generally a trivial matter. The complicated part is in the sending and receiving. Getting a program to not exit is usually just a matter of using a loop, or having everything execute in the context of a GUI where the network i/o thread(s) has nothing to do with the application lifetime at all.
> Basically, the client should: > - Connect to the server (at specific IP/port) > - Respond to any message it gets from server (once connected to the > server, client should be continuously running, waiting for messages > and and call respond appropriately). Depending on your preference, the Socket or "client" classes (UdpClient, TcpClient) are likely to provide what you need.
> So, this way, if there are multiple messages that server is sending to > client at the same time, client should be able to handle it (so this [quoted text clipped - 3 lines] > > Is this feasible? if yes, then can you give some examples? MSDN has a number of code samples, some better than others. I'm not aware of any specific ones that are better, though they may exist. The basic idea is not complicated though. In the context of .NET, you have two main approaches: one thread per connection, or using the asynchronous API. IMHO the latter is better and in fact can be clearer in code as well. But depending on your experience level, one thread per connection might be easier to grasp initially.
You should look at the MSDN documentation for the Socket, TcpClient, and UdpClient classes. They provide a variety of samples and explanations for how one might use the classes. In addition, if you know very little about socket programming, IMHO you should start with the simplest samples:
1) Simple UDP client/server setup where you have two endpoints, each only ever sending a single message then waiting for a reply.
2) Simple TCP client/server setup, similar to sample #1.
You should also review the Winsock FAQ: http://tangentsoft.net/wskfaq/
If you're going to use TCP, pay particular attention to these pages, as they cover one of the most common mistakes people new to network programming make: http://tangentsoft.net/wskfaq/articles/effective-tcp.html http://tangentsoft.net/wskfaq/intermediate.html#tcp
Pete
Jeroen Mostert - 12 Feb 2008 20:51 GMT <snip>
> You should also review the Winsock FAQ: > http://tangentsoft.net/wskfaq/ [quoted text clipped - 4 lines] > http://tangentsoft.net/wskfaq/articles/effective-tcp.html > http://tangentsoft.net/wskfaq/intermediate.html#tcp I'm going to quote this just to highlight it again, because many people are not only unaware of these issues, but often think that using .NET means they don't have to know these things -- because Winsock is "lower level". In reality, the .NET classes are relatively thin wrappers around the core Winsock functionality (and they certainly will not change the essential nature of TCP/IP), and you cannot afford not to know anything about it.
A common mistake I've seen in our company's codebase, for example, is people rudely slamming connections shut because they don't know how to do proper shutdowns. This is not a big problem as long as your applications are frolicking around on a LAN, but once they hit the Internet, it can complicate things quickly.
 Signature J.
asharda@woh.rr.com - 12 Feb 2008 22:08 GMT > <snip>> You should also review the Winsock FAQ: > >http://tangentsoft.net/wskfaq/ [quoted text clipped - 20 lines] > -- > J. Thanks J.
- I wrote a quick/dirty synchronous client as a basic POC. It appears to communicate with Server and exits out. - I am thinking of going the async (delegate/callback) way and see how it goes. I am hoping that a 'loop' won't eat up on cpu (i tried doing a loop with sync and cpu-usage on my xp went to around 50%).
I will go through the links you have provided. R
Peter Duniho - 12 Feb 2008 22:33 GMT > [...] > - I wrote a quick/dirty synchronous client as a basic POC. It appears > to communicate with Server and exits out. > - I am thinking of going the async (delegate/callback) way and see how > it goes. I am hoping that a 'loop' won't eat up on cpu (i tried doing > a loop with sync and cpu-usage on my xp went to around 50%). Sounds like polling. Don't poll. If you have a loop in a thread, it should either be doing useful work, or it should be waiting for some other thread to tell it to do something. You should never have a loop that just sits there looping.
Pete
asharda@woh.rr.com - 14 Feb 2008 13:54 GMT On Feb 12, 5:33 pm, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com> wrote:
> > [...] > > - I wrote a quick/dirty synchronous client as a basic POC. It appears [quoted text clipped - 9 lines] > > Pete Ok, i did 'some form' of async programming (well, not even sure if it can be called async-programming). My cpu-usage is back to normal (0% - 1%). But the occasional problem i am seeing is when server sends two messages at the same time.....in some instances client gets only one message (i tested the server-end with another client-async-program that somebody else had written and there is no such issue there....so, server-end appears to be working ok).
Here is a high-level steps of what i wrote (console app):
- Connect() //server-IP/port# - SendMessageToServer() - ReadDataFromServer() { ReadComplete = new AutoResetEvent(false); IAsyncResult asyncRes = stream.BeginRead(bufferName, 0,bufferName.Length,new AsyncCallBack(ReadAsyncData),stream); ReadComplete.WaitOne(); }
- ReadAsyncData(IAsyncResult asyncRes) { int bytesRd = ns.EndRead(asyncRes); fullData = String.Concat(fullData,Encoding.ASCII.GetString(bufferName,0,bytesRd);
if (bytesRd > 0) { ProcessData and send message to Server if need be..... stream.BeginRead(bufferName,0,bufferName.Length,new AsyncCallBack(ReadAsyncData),stream); } else ReadComplete.Set(); }
For clarity-purposes, i have shown the relevant data above.
I am not sure if this is a truly an asnc program or an attempt for async-program but has bits/pieces of sync-programming...
Any suggestions/advice on possible changes and why i am seeing the above mentioned problem?
Thanks. RS
Peter Duniho - 14 Feb 2008 19:20 GMT > Here is a high-level steps of what i wrote (console app): > [quoted text clipped - 7 lines] > ReadComplete.WaitOne(); > } So, you want this part to just sit and wait until the stream is closed. Right?
> - ReadAsyncData(IAsyncResult asyncRes) > { > int bytesRd = ns.EndRead(asyncRes); > fullData = > String.Concat(fullData,Encoding.ASCII.GetString(bufferName,0,bytesRd); Shouldn't you wait until you've checked "bytesRd" before bother to try to decode the data? I don't think you'll get an error here, but it still seems like bad form.
> if (bytesRd > 0) > { > ProcessData and send message to Server if need be..... What does "ProcessData" do? Are you prepared to receive a partial message? Are you prepared to receive two messages combined in the same receive? If the answer to either of those is "no", you have a bug.
> stream.BeginRead(bufferName,0,bufferName.Length,new > AsyncCallBack(ReadAsyncData),stream); [quoted text clipped - 7 lines] > I am not sure if this is a truly an asnc program or an attempt for > async-program but has bits/pieces of sync-programming... For a console application that is specifically supposed to connect to a single server a single time and exit when that connection has been closed, it looks fine to me. YMMV. :)
> Any suggestions/advice on possible changes and why i am seeing the > above mentioned problem? Well, you didn't post a complete sample, so it's not really possible to answer specific questions. However, I refer you to the links I mentioned before. Based on the vague description of the behavior you're seeing, it _could_ be that you are making invalid assumptions about the grouping of data sent to you.
Pete
asharda@woh.rr.com - 17 Mar 2008 20:55 GMT Hello guys,
Finally, able to get back on this.
Pete, - Yep, i want that part to wait until the stream is closed. - You are correct, no point in reading bytes until bytesRd has been checked. - You mentioned about 'Are you ready to receive two messages combined in the same receive?'. Can you elaborate on this? Could this be the cause of the problem i discussed above (occasionally, when the server tries to send two messages simultaneously, only one gets captured/ processed and not the other one)? Is there a way to find out if complete message has been received (before we proceed with processing?)
If more information is needed, I can try and send code-snippets (I had assumed that the code provided in the earlier postings would be sufficient to help resolve/pin-point the issue).
On Feb 14, 3:20 pm, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com> wrote:
> > Here is a high-level steps of what i wrote (console app): > [quoted text clipped - 55 lines] > > Pete Peter Duniho - 17 Mar 2008 23:04 GMT > [...] > - You mentioned about 'Are you ready to receive two messages combined > in the same receive?'. Can you elaborate on this? TCP is a stream of bytes, without any grouping imposed on it. No matter what grouping you (or whatever transmitter) used when you sent the bytes out, when the bytes arrive they may have any other arbitrary grouping. The bytes are guaranteed to be in the same order in which they were sent, but there is no other guarantee.
This means, for example, if the sender sends two groups of bytes in short succession, those two groups may be combined into a single group and sent together. It is up to the receiver to correctly determine where the first group ends and the second group begins. If the receiver is assuming that it will only receive one group at a time, then it could easily wind up receiving both groups but ignore the second because it only expected the first.
This bug will manifest itself as appearing to simply "miss" the second group of bytes.
Note that the above is just one example. Again, the actual grouping of bytes when you receive can be _anything_. You could receive just one byte at a time, you could receive a few bytes, then all of the rest of them, you could receive half of the first group, then the second half plus the first half of the second group, then the second half of the second group, or any other combination you can imagine.
It is up to you to write the code so that you take bytes that are streamed to you, and organize them as you need them to be.
> Could this be the > cause of the problem i discussed above (occasionally, when the server > tries to send two messages simultaneously, only one gets captured/ > processed and not the other one)? Yes, it could easily create that situation. That's why I pointed it out as a potential problem.
> Is there a way to find out if > complete message has been received (before we proceed with > processing?) If there's not, then you have a flaw in your application protocol. Your application protocol needs to be defined in such a way that the receiver can determine where the message boundaries exist in the stream of data that TCP provides, as TCP will not itself do this for you.
So, while I can't answer the question you asked (you haven't offered enough details regarding your application protocol), I can at least tell you that if your application protocol is correct, the answer is "yes". If the answer is "no", then you need to fix the protocol.
Pete
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|