I’m trying to write a asynchronous socket in c#. I read a lot of msdn articles and found those two examples: server, client.
I understood the sample code an use this to implement my own async socket. In the example the server checks for <EOF> to determine the end of the stream and send a response. I would like to know without checking for a special literal when the stream ends. My idea was to check (bytesRead > 0) and call handler.BeginReceive() recursively.
See following:
Original
if (bytesRead > 0) {
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(
state.buffer,0,bytesRead));
// Check for end-of-file tag. If it is not there, read
// more data.
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -1) {
// All the data has been read from the
// client. Display it on the console.
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
content.Length, content );
// Echo the data back to the client.
Send(handler, content);
} else {
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
My idea
if (received > 0)
{
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, received));
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
}
else
Send(handler, state.sb.ToString());
If I replace the original part with my part the program stops running.
I guess the client execute EndSend() in SendCallback() and block the Thread after receiveDone.WaitOne() in StartClient(). How could I pass this? Is it necessary to use a token which determine the end of the stream?
Are there any other good example codes? I just found those two.
(Evidence. The server should receive online clients and put them into a circulate buffer from this buffer he should read and process the records with multithreads. )
Edit
If I use folling:
if (receive > 0)
state.sb.Append(Encoding.UTF8.GetString(state.buffer, 0, receive));
if (receive == StateObject.BufferSize)
state.listener.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
else
Send(state.listener, state.sb.ToString());
Everyting works fine, I guess. Is it ok? Or miss I something?
If I combine the two ifs, it doesn’t work again. Why?
if(receive > 0 || receive == StateObject.BufferSize) -> if(receive > 0) // Not working.
The problem with your version of code is that you initiate BeginReceive always but in one situation i.e. when there are 0 bytes received. In fact the end of transmission will occur most of the time when you receive an amount of data that is non-zero and less than your buffer size (and sometimes when it is exactly the size of the buffer). Receiving 0 bytes will never happen because that means no transmission rathen than end of transmission. That is assuming that sender ends transmission by closing connection.
There is number of ways to indicate end of transmission:
Problem with first approach is that closing (and reopening) connection is usually expensive.
Problem with header is that if you miss a header (because of some network problem) you are lost - you do not know when the next header will come because you do not know when the current data packet will end (lost header). Easiest recovery in case of problems provides EOF in some form. It does not have to literally be <EOF> string, it can be anything that would (most probably) never occur in your normal data stream.
Having said that, there is nothing stopping you from using combination of header with EOF or a header which would contain a special sequence marking beginning of a record.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With