我對在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