writing an async client (sockets/async/thread)

A

asharda

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.
 
P

Peter Duniho

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).

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
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?

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
 
J

Jeroen Mostert

Peter Duniho wrote:
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
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.
 
A

asharda

Peter Duniho wrote:




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.

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
 
P

Peter Duniho

[...]
- 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
 
A

asharda

[...]
- 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 theasync(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

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
 
P

Peter Duniho

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();
}

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);
}
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...

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
 
A

asharda

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).
 
P

Peter Duniho

[...]
- 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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top