异步套接字接收的数据顺序错误或丢失
本文关键字:错误 顺序 数据 套接字 异步 | 更新日期: 2023-09-27 18:17:19
我以前问过这个话题,并认为我已经掌握了它,但我发现我在这里错过了一些东西。我在linux中有一些C代码,我通过套接字发送数据到我的c# winforms可视化代码。我用最快的速度从C发送数据,这是相当快的。但是在c#中,我的datagridview没有正确更新。如果我放慢向c#代码发送数据的速度,它就可以了。但我真的做不到。我真的要死了。
在c#中是这样的:
{
. . .
sListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sListener.Bind(new IPEndPoint(0, 1994));
Listen();
}
private void Listen()
{
sListener.Listen(10);
// Begins an asynchronous operation to accept an attempt
AsyncCallback aCallback = new AsyncCallback(AcceptCallback);
sListener.BeginAccept(aCallback, sListener);
}
public void AcceptCallback(IAsyncResult ar)
{
Socket listener = null;
// A new Socket to handle remote host communication
Socket handler = null;
try
{
// Receiving byte array
byte[] buffer = new byte[1024];
// Get Listening Socket object
listener = (Socket)ar.AsyncState;
// Create a new socket
handler = listener.EndAccept(ar);
// Using the Nagle algorithm
handler.NoDelay = false;
// Creates one object array for passing data
object[] obj = new object[2];
obj[0] = buffer;
obj[1] = handler;
// Begins to asynchronously receive data
handler.BeginReceive( buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), obj);
// Begins an asynchronous operation to accept an attempt
AsyncCallback aCallback = new AsyncCallback(AcceptCallback);
listener.BeginAccept(aCallback, listener);
}
catch (Exception exc) { MessageBox.Show(exc.ToString()); }
}
public void ReceiveCallback(IAsyncResult ar)
{
try
{
// Fetch a user-defined object that contains information
object[] obj = new object[2];
obj = (object[])ar.AsyncState;
// Received byte array
byte[] buffer = (byte[])obj[0];
// A Socket to handle remote host communication.
handler = (Socket)obj[1];
// Received message
string content = string.Empty;
// The number of bytes received.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
Array.Resize(ref buffer, bytesRead);
double[] values = new double[buffer.Length / 8];
int i = 0;
values[i] = BitConverter.ToDouble(buffer, i * 8);
values[++i] = BitConverter.ToDouble(buffer, i * 8);
values[++i] = BitConverter.ToDouble(buffer, i * 8);
values[++i] = BitConverter.ToDouble(buffer, i * 8);
values[++i] = BitConverter.ToDouble(buffer, i * 8);
this.Invoke((MethodInvoker)delegate()
{
if (dataGridView1.Rows.Count > 5)
{
dataGridView1.Rows.RemoveAt(this.dataGridView1.Rows[5].Index);
}
dataGridView1.Rows[0].Cells[1].Value = values[0];
dataGridView1.Rows[1].Cells[1].Value = values[1];
dataGridView1.Rows[2].Cells[1].Value = values[2];
dataGridView1.Rows[3].Cells[1].Value = values[3];
dataGridView1.Rows[4].Cells[1].Value = values[4];
});
}
// Continues to asynchronously receive data
byte[] buffernew = new byte[1024];
obj[0] = buffernew;
obj[1] = handler;
handler.BeginReceive(buffernew, 0, buffernew.Length,
SocketFlags.None,
new AsyncCallback(ReceiveCallback), obj);
}
catch (Exception exc) { MessageBox.Show(exc.ToString()); }
}
你的异步代码正在触发异步,这是预期的…但这意味着处理的顺序可能与接收的顺序不同。例如:
.NET receive message 1
.NET receive message 2
.NET finish receive message 2
.NET finish receive message 1
这里你假设你会看到1,然后是2,因为这是它们被接收的顺序,但不是它们被接收的顺序。
如果你的数据的顺序很重要,你必须一次发送所有的数据在一个大的批处理(坏),或接收它顺序(底层TCP应该确保消息以适当的顺序传递)。