我对在C#中使用异步套接字方法的正确方式感到困惑。我将参考这两篇文章来解释一些事情并提出我的问题:MSDN article on asynchronous client sockets和devarticles.com article on socket programming。C中的异步套接字#
我的问题是关于BeginReceive()
方法。 MSDN文章使用这两个函数来处理接收数据:虽然devarticles.com教程为BeginReceive
方法的最后一个参数传递null
private static void Receive(Socket client)
{
try
{
// Create the state object.
StateObject state = new StateObject();
state.workSocket = client;
// Begin receiving the data from the remote device.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
// Retrieve the state object and the client socket
// from the asynchronous state object.
StateObject state = (StateObject) ar.AsyncState;
Socket client = state.workSocket;
// Read data from the remote device.
int bytesRead = client.EndReceive(ar);
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));
// Get the rest of the data.
client.BeginReceive(state.buffer,0,StateObject.BufferSize,0,
new AsyncCallback(ReceiveCallback), state);
}
else
{
// All the data has arrived; put it in response.
if (state.sb.Length > 1)
{
response = state.sb.ToString();
}
// Signal that all bytes have been received.
receiveDone.Set();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
,并接着解释说,最后一个参数是有用的,当我们”重新处理多个套接字。现在,我的问题是:
什么是传递一个状态到
BeginReceive
方法,如果我们只用一个单一的插座工作的呢?是否要避免使用类字段?这似乎没有什么意义,但也许我错过了一些东西。如何与多个插座打交道时的状态参数的帮助?如果我打电话给
client.BeginReceive(...)
,是不是所有的数据都会从client
插座上读取?该devarticles.com教程使它在此调用听起来像:m_asynResult = m_socClient.BeginReceive (theSocPkt.dataBuffer,0,theSocPkt.dataBuffer.Length, SocketFlags.None,pfnCallBack,theSocPkt);
数据将从theSocPkt.thisSocket
套接字读取,而不是从m_socClient
插座。在他们的例子中,两者是一样的,但如果情况并非如此,会发生什么?
我实在不明白这其中最后一个参数是非常有用的,或至少它如何与多个插座帮助。如果我有多个套接字,我仍然需要每个都调用BeginReceive
,对吧?
而程序员负责确保包含在状态对象的插座是一样的Socket对象从'BeginReceive'叫,是否正确?我猜如果他们不同,那会导致错误。 – IVlad 2010-03-27 10:59:11
这不是必需的 - .NET保证即使您同时有多个呼叫,也能可靠地传输状态。当你调用一个普通的函数时,你不必检查你收到的参数是否与调用者用来呼叫你的参数相同。如果你这样做了,能够传递参数将没有实际价值,因为无论如何您都必须参考原始对象才能比较它们。 – 2010-03-27 11:05:54
这不是我的意思。例如,考虑这个:'BeginReceive'回调函数内的'Socket client = state.workSocket;'。考虑在执行'state.workSocket = B'后,名为'BeginReceive'的套接字'A'传递给'StateObject状态'。这只有在“A == B”时才有效,对吗?我有点困惑,因为所有的例子都将相同的套接字传递给用来调用receive方法的状态,但是没有一个明确地说这两个套接字必须是相同的。我认为他们应该,但我想确保情况是这样的。 – IVlad 2010-03-27 11:13:35