"Buffer full" exception when BufferedWaveProvider is being filled in another thread - c#

I have two BufferedWaveProviders and MixingSampleProvider. The first BufferedSampleProvider (myBuffer) is for my audio comming from soundcard. The second BufferedWaveProvider (incomingBuffer) is for audio comming from network (TCP).
incomingBuffer is being filled asynchronously like that:
private static void Receive()
{
receiver.BeginReceive(incomingBytes, 0, incomingBytes.Length, SocketFlags.None, ReceiveCallback, null);
}
private static void ReceiveCallback(IAsyncResult ar)
{
receiver.EndReceive(ar);
incomingBuffer.AddSamples(incomingBytes, 0 , incomingBytes.Length);
Receive();
}
But after 7-10 second after starting the program it finishes because of exception.
How should I fill the buffer asynchronously?

Stop ignoring the return value of EndReceive.
It tells you how many bytes of data you received. That's how many samples you have to add to your buffer (though make sure that you're not converting samples to bytes and vice versa incorrectly).
Instead, now you're simply passing your incomingBytes to the incomingBuffer whole, always - even if you only received a single byte over TCP. This is garbage data, and it fills your buffer quicker than it can drain.
In general, return values of methods and functions are meaningful, and ignoring them should only be done when you understand what you're ignoring (e.g. if you don't care about handling anything but the callback, ignoring the return value of BeginReceive is fine; if you need to know whether there's a pending asynchronous I/O request, you need the return value).

Related

C# Async Sockets: How much data does the Socket store when the call to BeginReceive is delayed?

I am using C#'s async Sockets and use BeginReceive to read data from the Socket into a byte[]-Buffer of 8192 bytes. But what happens, when new packet come in before BeginReceive is called again? My current setup handles about 3 incoming messages before it stops. I'm assuming that the Socket must store the incoming data somewhere before it can be processed by BeginReceive.
Do I have any control over how much data the Socket buffers before it stops?
Do I have to rely on processing the incoming messages fast enough in order not to "miss" any?
What happen, when the ProcessMessageBuffer method in the example below takes so long (for some reason) that the incoming data starts to pile up in the Socket?
public void ReadCallback(IAsyncResult ar)
{
// We have a new TCP Packet!
int bytesReceived = 0;
try
{
// The amount of bytes we have just received
bytesReceived = Socket.EndReceive(ar);
}
catch (SocketException ex)
{
// The client closed the connection
OnSocketException(new SocketExceptionEventArgs(ex));
}
if (bytesReceived > 0)
{
// We have received some data. Write it to the MessageBuffer
MessageBuffer.Write(ReceiveBuffer, 0, bytesReceived);
// Process the Messages that may be stored in the MessageBuffer
// What happens, if this takes too long?
ProcessMessageBuffer(MessageBuffer.ToArray());
// Get ready to receive more data
Socket.BeginReceive(ReceiveBuffer, 0, ReceiveBuffer.Length, SocketFlags.None, new AsyncCallback(ReadCallback), null);
}
}
Network I/O is buffered at every step of the way. So it's hard to know which "buffer" you are worried about.
From Socket.ReceiveBufferSize:
…The default is 8192.A larger buffer size potentially reduces the number of empty acknowledgements (TCP packets with no data portion), but might also delay the recognition of connection difficulties. Consider increasing the buffer size if you are transferring large files, or you are using a high bandwidth, high latency connection (such as a satellite broadband provider.)
From your question:
Do I have any control over how much data the Socket buffers before it stops?
You have at least a few strategies available:
Modify the ReceiveBufferSize property value. This will change the size of the buffer in the socket object.
Use a larger buffer in your call to BeginReceive(). This will provide the Socket object with more space into which it can write before it can no longer empty its own buffer. Note that the buffer you pass to Socket will be pinned until the receive operation completes, which can have implications on memory heap management.
Issue multiple BeginReceive() calls. This has a similar effect as providing a larger buffer, but gives you finer granularity of control over the buffers. It comes with the complication that, due to how Windows schedules threads, you may wind up executing the callback for the receive operation completions in a different order than you called BeginReceive() in the first place. The data will be in the right order, according to the order of the BeginReceive() calls and each buffer you passed, but those buffers may appear to your code to get filled out of order (they aren't really, but the thread handling a later-filled buffer might get to run before the thread handling an earlier-filled buffer).
See socket buffer size: pros and cons of bigger vs smaller for some additional details.
Do I have to rely on processing the incoming messages fast enough in order not to "miss" any?
No. TCP is reliable. If you don't process data quickly enough, all that will happen is that the remote endpoint will have to wait to send more data.
That said, you should work very hard to make your socket I/O code work as quickly as possible. If you have some processing that is slow enough to delay receive operations, you should off-load that processing to a completely independent thread, buffering the received data yourself (e.g. with a MemoryStream, FileStream, a queue of some sort, etc.).
If you do it that way, then you likely won't have to do anything beyond the simple, default handling of socket. You'll be able to have a single BeginReceive() outstanding at once, you won't have to adjust the socket's buffer, and you'll be able to allocate "normal-sized" byte[] objects (or keep a single one around for reuse).

sending a large amount of data throught TCP socket

This is my first question posted on this forum, and I'm a beginner in c# world , so this is kind of exciting for me, but I'm facing some issues with sending a large amount of data through sockets so this is more details about my problem:
I'm sending a binary image of 5 Mo through a TCP socket, at the receiving part I'm saving the result(data received ) and getting only 1.5 Mo ==> data has been lost (I compared the original and the resulting file and it showed me the missed parts)
this is the code I use:
private void senduimage_Click(object sender, EventArgs e)
{
if (!user.clientSocket_NewSocket.Connected)
{
Socket clientSocket_NewSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
user.clientSocket_NewSocket = clientSocket_NewSocket;
System.IAsyncResult _NewSocket = user.clientSocket_NewSocket.BeginConnect(ip_address, NewSocket.Transceiver_TCP_Port, null, null);
bool successNewSocket = _NewSocket.AsyncWaitHandle.WaitOne(2000, true);
}
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(Uimage_Data);
user.clientSocket_NewSocket.Send(outStream);
}
In forums they say to divide data into chunks, is this a solution, if so how can I do this, I've tried but it didn't work!
There are lots of different solutions but chunking is usually a good solution, you can either do this blindly where you keep filling your temporary buffer and then putting it into some stateful buffer until you hit some arbitrary token or the buffer is not completely full, or you can adhere to some sort of contract per tcp message (a message being the overall data to recieve).
If you were to look at doing some sort of contract then do something like the first N bytes of a message is the descriptor, which you could make as big or as small as you want, but your temp buffer will ONLY read this size up front from the stream.
A typical header could be something like:
public struct StreamHeader // 5 bytes
{
public byte MessageType {get;set;} // 1 byte
public int MessageSize {get;set;} // 4 bytes
}
So you would read that in then if its small enough allocate the full message size to the temp buffer and read it all in, or if you deem it too big chunk it into sections and keep reading until the total bytes you have received match the MessageSize portion of your header structure.
Probably you haven't read the documentation on socket usage in C#. (http://msdn.microsoft.com/en-us/library/ms145160.aspx)
The internal buffer can not store all the data you provided to send methode. A possible solution to your problem can be is like you said to divide your data into chunks.
int totalBytesToSend = outstream.length; int bytesSend = 0;
while(bytesSend < totalBytesToSend )
bytesSend+= user.clientSocket_NewSocket.Send(outStream, bytesSend, totalBytesToSend - bytesSend,...);
I suspect that one of your problems is that you are not calling EndConnect. From the MSDN documentation:
The asynchronous BeginConnect operation must be completed by calling the EndConnect method.
Also, the wait:-
bool successNewSocket = _NewSocket.AsyncWaitHandle.WaitOne(2000, true);
is probably always false as there is nothing setting the event to the signaled state. Usually, you would specify a callback function to the BeginConnect function and in the callback you'd call EndConnect and set the state of the event to signaled. See the example code on this MSDN page.
UPDATE
I think I see another problem:-
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(Uimage_Data);
I don't know what type Uimage_Data but I really don't think you want to convert it to ASCII. A zero in the data may signal an end of data byte (or maybe a 26 or someother ASCII code). The point is, the encoding process is likely to be changing the data.
Can you provide the type for the Uimage_Data object?
Most likely the problem is that you are closing the client-side socket before all the data has been transmitted to the server, and it is therefore getting discarded.
By default when you close a socket, all untransmitted data (sitting in the operating system buffers) is discarded. There are a few solutions:
[1] Set SO_LINGER (see http://developerweb.net/viewtopic.php?id=2982)
[2] Get the server to send an acknowledgement to the client, and don't close the client-side socket until you receive it.
[3] Wait until the output buffer is empty on the client side before closing the socket (test using getsocketopt SO_SND_BUF - I'm not sure of the syntax on c#).
Also you really should be testing the return value of Send(). Although in theory it should block until it sends all the data, I would want to actually verify that and at least print an error message if there is a mismatch.

C# SocketAsyncEventArgs not sending all data

I have a problem with the SocketAsyncEventArgs class..the problem is when I try to send 8K of data
for example over internet, the socket sometimes only sends 1K or 2K, I know that this is normal for
TCP socket and that one send doesn't guarantee one receive.
now for this to work for me I modified my code to resend the remaining data, for example
when I the SocketAsyncEventArgs.SendAsync completes, in the callback i check whether it sent all the 8K or not if it's not, I call the SocketAsyncEventArgs.SendAsync again with the remaining data untill
I send it all.
Now, when I looked at some SocketAsyncEventArgs code.. I saw that most people don't do so!
and they just clean up when the send complete without checking if it sent all the data or not!
also when I looked at Microsoft's example, they were saying the ONE call to SocketAsyncEventArgs.SendAsync guarantees that all the data will be sent.
I mean I tested it myself and NO all data will not be sent in one call to SocketAsyncEventArgs.SendAsync.
What I'm doing wrong ?
thanks in advance.
Edit:
Here is the code which doesn't send all data(exactly like microsoft's)
the SendAsyncComplete will be called when the socket sends for example 1Kb of data
not all 8K!
public virtual void Send(byte[] packet, int offset, int length)
{
if (_tcpSock != null && _tcpSock.Connected)
{
var args = SocketHelpers.AcquireSocketArg();
if (args != null)
{
args.Completed += SendAsyncComplete;
args.SetBuffer(packet, offset, length);
args.UserToken = this;
var willRaiseEvent = _tcpSock.SendAsync(args);
if (!willRaiseEvent)
{
ProcessSend(args);
}
unchecked
{
_bytesSent += (uint)length;
}
Interlocked.Add(ref _totalBytesSent, length);
}
else
{
log.Error("Client {0}'s SocketArgs are null", this);
}
}
}
private static void ProcessSend(SocketAsyncEventArgs args)
{
args.Completed -= SendAsyncComplete;
SocketHelpers.ReleaseSocketArg(args);
}
private static void SendAsyncComplete(object sender, SocketAsyncEventArgs args)
{
ProcessSend(args);
}
There are many things I would change there. As a preamble, read this.
First of all, whenever you sent any data on the socket, you must process that event: either you stop the whole send process, or you issue another socket send operation to send the remaining data.
So it makes sense to have 3 methods, like this:
// This is the Send() to be used by your class' clients
1) public void Send(byte[] buffer);
This method will take care to apply any data formatting that you need, create (retrieve) a SocketAsyncEventArgs object, set the token to hold your buffer, and call the next method bellow:
2) private void Send(SocketAsyncEventArgs e);
This one actually calls
Socket.SendAsync(SocketAsyncEventArgs e)
and copies the contents from the token (the buffer, remember?) to the SAEA object. Now that is why because method number (2) might be called several times to send the remaining data that couldn't be sent in one operation by the socket. So here you copy the remaining data from the token to the SAEA buffer.
3) private void ProcessSent(SocketAsyncEventArgs e);
This last method will examine the data that has been sent by the socket. If all the data has been sent, the SAEA object will be released. If not, method (2) will be called again for the rest of the data. In order to keep track of sent data, you use SAEA.BytesTransferred. You should add this value to a value stored in the custom token I advise you to create (so do not use "this" as a token).
This is where you also check for SocketError on the SAEA parameter.
This last method will be called in two places:
in the 2nd method, like this:
// Attempt to send data in an asynchronous fashion
bool isAsync = this.Socket.SendAsync(e);
// Something went wrong and we didn't send the data async
if (!isAsync)
this.ProcessSent(e);
This bit is important any many people missed it even when using the more traditional Begin/EndXXX pattern (in that case, via IAsyncResult). If you don't place it, once in a while (quite rare), a StackOverflow exception will pop out of nowhere and will keep you puzzled for long time.
in the Completed event handler:
private void Completed(object sender, SocketAsyncEventArgs e)
{
// What type of operation did just completed?
switch (e.LastOperation)
{
case SocketAsyncOperation.Send:
{
ProcessSent(e);
break;
}
}
}
The tricky thing is to use one SocketAsyncEventArgs object per 1st Send(byte[]) operation, and release it in 3rd operation, if all data has been sent.
For that, you must create a custom token (class or immutable struct) to place in SocketAsyncEventArgs.UserToken inside the 1st method, and then keep track of how much data you have transferred on each Socket.SendAsync() operation.
When you are reading the article provided in the beginning, notice how the writer reuses the same SAEA object when at the end of Send() operation proceeds with a Receive() operation, if all the data has been sent. That is because his protocol is: each one of the parties (server and client) talk to each other in turns.
Now, should multiple calls to the 1st Send() method occur at the same time, there is no rule in which order they will be handled by the OS. If that is likely to happen and message order is important, and since any call to Send(byte[]) from an "outside entity" result in a Socket.SendAsync(), I suggest that the 1st method actually writes down the received bytes in an internal buffer. As long as this buffer is not empty, you keep sending this data internally. Think of it like a producer-consumer scenario, where the "outside entity" is the producer and the internal send op is the consumer. I prefer an optimistic concurrency scenario here.
The documentation on the matter is rather shallow, with the exception of this article, and even in this case, when you start implementing your own application, some things turn out to be different. This SocketAsyncEventArgs model is arguably a bit counter-intuitive.
Let me know if you need more help, I had my times of struggle with this a while ago when I developed my own library.
Edit:
If I were you, I would move
unchecked
{
_bytesSent += (uint)length;
}
Interlocked.Add(ref _totalBytesSent, length);
to your ProcessSend(SAEA), and use args.BytesTransferred instead of "length".

What is the purpose of the SerialPort write buffer?

From outside SerialPort object, it seems to make no difference what the size of the write buffer is, and whether or not it is full.
Using synchronous writing, the write method blocks until all the data has been sent and the buffer is empty.
Using async writing, the data is queued and the program continues on going. The callback method is not called until the write operation is completed and the data is out of the buffer.
The behavior of the serialport object seems to be the same regardless of how much data is in the buffer and whether or not the buffer is full. No errors seem to happen when the write buffer is full.
So, why be able to check BytesToWrite and WriteBufferSize at all? Is there any way that SerialPort behaves differently when the write buffer is full?
Buffers are a mechanism designed to allow whoever processes the buffer to do it in their own way, at their own time.
When i send data, i want it to be pushed at the maximal rate of the port, but i don't want to busywait on the port and wait for each byte to be sent before i push the next one. So you have a processing buffer that feeds the hardware, and can be passed in chunks.
As for the why you'd want to check the BytesToWrite - you are often interested to know if all your data was sent before moving on to the next thing you want to do, you might expect a response after a given period of time, you might want to know what the actual transfer rate is etc'.
The C# SerialPort.BytesToWrite property corresponds to the unmanaged Win32 COMSTAT.cbOutQue field which is described as:
The number of bytes of user data remaining to be transmitted for all write operations. This value will be zero for a nonoverlapped write.
This seems to suggest you could observe the write buffer being consumed as it is sent with async writing before the write complete callback is called.
I wanted to create a test utility that constantly sends out 0xAA out the serial port, with no gaps, forever. I don't care about RX.
I used a timer to keep the buffer full, and monitored BytesToWrite to wait below it was below threshold, before I wrote more data into the buffer.
I could have alternatively not used a timer, but refreshed the serial port in the AsyncCallback, but I wanted to do it this way for fun. You can view the label11 to see the buffer fill and empty.
Note you can get away with BeginWrite without EndWrite for a short time, but eventually you will run out resources. I am basically just putting in a dummy EndWrite.
private void checkBox2_CheckedChanged(object sender, EventArgs e)
{
timerFill.Enabled = checkBox2.Checked;
}
private void timerFill_Tick(object sender, EventArgs e)
{
GenerateSquareWave();
}
int const bufferSize = 256;
void GenerateSquareWave()
{
int k = serialPort1.BytesToWrite;
label11.Text = k.ToString();
if (k < bufferSize)
{
byte[] data = new byte[bufferSize];
for (int i = 0; i < bufferSize; i++)
{
data[i] = 0xAA;
}
serialPort1.BaseStream.BeginWrite(data, 0, data.Length, new AsyncCallback((IAsyncResult ar) => serialPort1.BaseStream.EndWrite(ar)), null);
}
}

C# Begin/EndReceive - how do I read large data?

When reading data in chunks of say, 1024, how do I continue to read from a socket that receives a message bigger than 1024 bytes until there is no data left? Should I just use BeginReceive to read a packet's length prefix only, and then once that is retrieved, use Receive() (in the async thread) to read the rest of the packet? Or is there another way?
edit:
I thought Jon Skeet's link had the solution, but there is a bit of a speedbump with that code. The code I used is:
public class StateObject
{
public Socket workSocket = null;
public const int BUFFER_SIZE = 1024;
public byte[] buffer = new byte[BUFFER_SIZE];
public StringBuilder sb = new StringBuilder();
}
public static void Read_Callback(IAsyncResult ar)
{
StateObject so = (StateObject) ar.AsyncState;
Socket s = so.workSocket;
int read = s.EndReceive(ar);
if (read > 0)
{
so.sb.Append(Encoding.ASCII.GetString(so.buffer, 0, read));
if (read == StateObject.BUFFER_SIZE)
{
s.BeginReceive(so.buffer, 0, StateObject.BUFFER_SIZE, 0,
new AyncCallback(Async_Send_Receive.Read_Callback), so);
return;
}
}
if (so.sb.Length > 0)
{
//All of the data has been read, so displays it to the console
string strContent;
strContent = so.sb.ToString();
Console.WriteLine(String.Format("Read {0} byte from socket" +
"data = {1} ", strContent.Length, strContent));
}
s.Close();
}
Now this corrected works fine most of the time, but it fails when the packet's size is a multiple of the buffer. The reason for this is if the buffer gets filled on a read it is assumed there is more data; but the same problem happens as before. A 2 byte buffer, for exmaple, gets filled twice on a 4 byte packet, and assumes there is more data. It then blocks because there is nothing left to read. The problem is that the receive function doesn't know when the end of the packet is.
This got me thinking to two possible solutions: I could either have an end-of-packet delimiter or I could read the packet header to find the length and then receive exactly that amount (as I originally suggested).
There's problems with each of these, though. I don't like the idea of using a delimiter, as a user could somehow work that into a packet in an input string from the app and screw it up. It also just seems kinda sloppy to me.
The length header sounds ok, but I'm planning on using protocol buffers - I don't know the format of the data. Is there a length header? How many bytes is it? Would this be something I implement myself? Etc..
What should I do?
No - call BeginReceive again from the callback handler, until EndReceive returns 0. Basically, you should keep on receiving asynchronously, assuming you want the fullest benefit of asynchronous IO.
If you look at the MSDN page for Socket.BeginReceive you'll see an example of this. (Admittedly it's not as easy to follow as it might be.)
Dang. I'm hesitant to even reply to this given the dignitaries that have already weighed in, but here goes. Be gentle, O Great Ones!
Without having the benefit of reading Marc's blog (it's blocked here due the corporate internet policy), I'm going to offer "another way."
The trick, in my mind, is to separate the receipt of the data from the processing of that data.
I use a StateObject class defined like this. It differs from the MSDN StateObject implementation in that it does not include the StringBuilder object, the BUFFER_SIZE constant is private, and it includes a constructor for convenience.
public class StateObject
{
private const int BUFFER_SIZE = 65535;
public byte[] Buffer = new byte[BUFFER_SIZE];
public readonly Socket WorkSocket = null;
public StateObject(Socket workSocket)
{
WorkSocket = workSocket;
}
}
I also have a Packet class that is simply a wrapper around a buffer and a timestamp.
public class Packet
{
public readonly byte[] Buffer;
public readonly DateTime Timestamp;
public Packet(DateTime timestamp, byte[] buffer, int size)
{
Timestamp = timestamp;
Buffer = new byte[size];
System.Buffer.BlockCopy(buffer, 0, Buffer, 0, size);
}
}
My ReceiveCallback() function looks like this.
public static ManualResetEvent PacketReceived = new ManualResetEvent(false);
public static List<Packet> PacketList = new List<Packet>();
public static object SyncRoot = new object();
public static void ReceiveCallback(IAsyncResult ar)
{
try {
StateObject so = (StateObject)ar.AsyncState;
int read = so.WorkSocket.EndReceive(ar);
if (read > 0) {
Packet packet = new Packet(DateTime.Now, so.Buffer, read);
lock (SyncRoot) {
PacketList.Add(packet);
}
PacketReceived.Set();
}
so.WorkSocket.BeginReceive(so.Buffer, 0, so.Buffer.Length, 0, ReceiveCallback, so);
} catch (ObjectDisposedException) {
// Handle the socket being closed with an async receive pending
} catch (Exception e) {
// Handle all other exceptions
}
}
Notice that this implementation does absolutely no processing of the received data, nor does it have any expections as to how many bytes are supposed to have been received. It simply receives whatever data happens to be on the socket (up to 65535 bytes) and stores that data in the packet list, and then it immediately queues up another asynchronous receive.
Since processing no longer occurs in the thread that handles each asynchronous receive, the data will obviously be processed by a different thread, which is why the Add() operation is synchronized via the lock statement. In addition, the processing thread (whether it is the main thread or some other dedicated thread) needs to know when there is data to process. To do this, I usually use a ManualResetEvent, which is what I've shown above.
Here is how the processing works.
static void Main(string[] args)
{
Thread t = new Thread(
delegate() {
List<Packet> packets;
while (true) {
PacketReceived.WaitOne();
PacketReceived.Reset();
lock (SyncRoot) {
packets = PacketList;
PacketList = new List<Packet>();
}
foreach (Packet packet in packets) {
// Process the packet
}
}
}
);
t.IsBackground = true;
t.Name = "Data Processing Thread";
t.Start();
}
That's the basic infrastructure I use for all of my socket communication. It provides a nice separation between the receipt of the data and the processing of that data.
As to the other question you had, it is important to remember with this approach that each Packet instance does not necessarily represent a complete message within the context of your application. A Packet instance might contain a partial message, a single message, or multiple messages, and your messages might span multiple Packet instances. I've addressed how to know when you've received a full message in the related question you posted here.
You would read the length prefix first. Once you have that, you would just keep reading the bytes in blocks (and you can do this async, as you surmised) until you have exhausted the number of bytes you know are coming in off the wire.
Note that at some point, when reading the last block you won't want to read the full 1024 bytes, depending on what the length-prefix says the total is, and how many bytes you have read.
Also I troubled same problem.
When I tested several times, I found that sometimes multiple BeginReceive - EndReceive makes packet loss. (This loop was ended improperly)
In my case, I used two solution.
First, I defined the enough packet size to make only 1 time BeginReceive() ~ EndReceive();
Second, When I receive large size of data, I used NetworkStream.Read() instead of BeginReceive() - EndReceive().
Asynchronous socket is not easy to use, and it need a lot of understanding about socket.
For info (general Begin/End usage), you might want to see this blog post; this approach is working OK for me, and saving much pain...
There seems to be a lot of confusion surrounding this. The examples on MSDN's site for async socket communication using TCP are misleading and not well explained. The EndReceive call will indeed block if the message size is an exact multiple of the receive buffer. This will cause you to never get your message and the application to hang.
Just to clear things up - You MUST provide your own delimiter for data if you are using TCP. Read the following (this is from a VERY reliable source).
The Need For Application Data
Delimiting
The other impact of TCP treating
incoming data as a stream is that data
received by an application using TCP
is unstructured. For transmission, a
stream of data goes into TCP on one
device, and on reception, a stream of
data goes back to the application on
the receiving device. Even though the
stream is broken into segments for
transmission by TCP, these segments
are TCP-level details that are hidden
from the application. So, when a
device wants to send multiple pieces
of data, TCP provides no mechanism for
indicating where the “dividing line”
is between the pieces, since TCP
doesn't examine the meaning of the
data at all. The application must
provide a means for doing this.
Consider for example an application
that is sending database records. It
needs to transmit record #579 from the
Employees database table, followed by
record #581 and record #611. It sends
these records to TCP, which treats
them all collectively as a stream of
bytes. TCP will package these bytes
into segments, but in a manner the
application cannot predict. It is
possible that each will end up in a
different segment, but more likely
they will all be in one segment, or
part of each will end up in different
segments, depending on their length.
The records themselves must have some
sort of explicit markers so the
receiving device can tell where one
record ends and the next starts.
Source: http://www.tcpipguide.com/free/t_TCPDataHandlingandProcessingStreamsSegmentsandSequ-3.htm
Most examples I see online for using EndReceive are wrong or misleading. It usually causes no problems in the examples because only one predefined message is sent and then the connection is closed.
This a very old topic, but I got here looking for something else and found this:
Now this corrected works fine most of the time, but it fails when the packet's size is a multiple of the buffer. The reason for this is if the buffer gets filled on a read it is assumed there is more data; but the same problem happens as before. A 2 byte buffer, for exmaple, gets filled twice on a 4 byte packet, and assumes there is more data. It then blocks because there is nothing left to read. The problem is that the receive function doesn't know when the end of the packet is.
I had this same problem, and since none of the replies seems to solve this, the way I did it was using Socket.Available
public static void Read_Callback(IAsyncResult ar)
{
StateObject so = (StateObject) ar.AsyncState;
Socket s = so.workSocket;
int read = s.EndReceive(ar);
if (read > 0)
{
so.sb.Append(Encoding.ASCII.GetString(so.buffer, 0, read));
if (s.Available == 0)
{
// All data received, process it as you wish
}
}
// Listen for more data
s.BeginReceive(so.buffer, 0, StateObject.BUFFER_SIZE, 0,
new AyncCallback(Async_Send_Receive.Read_Callback), so);
}
Hope this helps others, SO have helped me many times, thank you all!

Categories