C# 如何在SocketAsyncEventArgs对象上使用缓冲区
我们不得不在SocketAsyncEventArgs对象上使用缓冲区 使用旧的套接字方法,我们将强制转换状态对象,如下所示:C# 如何在SocketAsyncEventArgs对象上使用缓冲区,c#,sockets,C#,Sockets,我们不得不在SocketAsyncEventArgs对象上使用缓冲区 使用旧的套接字方法,我们将强制转换状态对象,如下所示: clientState cs = (clientState)asyncResult.AsyncState; 然而,3.5框架是不同的 对于从客户端以块的形式到达的字符串,我们似乎无法确定缓冲区是如何工作的,因此我们可以在找到char3时处理整个字符串 当前代码: private void ProcessReceive(SocketAsyncEventArgs e) {
clientState cs = (clientState)asyncResult.AsyncState;
然而,3.5框架是不同的
对于从客户端以块的形式到达的字符串,我们似乎无法确定缓冲区是如何工作的,因此我们可以在找到char3时处理整个字符串
当前代码:
private void ProcessReceive(SocketAsyncEventArgs e)
{
string content = string.Empty;
// Check if the remote host closed the connection.
if (e.BytesTransferred > 0)
{
if (e.SocketError == SocketError.Success)
{
Socket s = e.UserToken as Socket;
//asyncResult.AsyncState;
Int32 bytesTransferred = e.BytesTransferred;
// Get the message received from the listener.
content += Encoding.ASCII.GetString(
e.Buffer, e.Offset, bytesTransferred);
if (content.IndexOf(Convert.ToString((char)3)) > -1)
{
e.BufferList = null;
// Increment the count of the total bytes receive by the server
Interlocked.Add(ref this.totalBytesRead, bytesTransferred);
}
else
{
content += Encoding.ASCII.GetString(
e.Buffer, e.Offset, bytesTransferred);
ProcessReceive(e);
}
}
else
{
this.CloseClientSocket(e);
}
}
}
首先,我要说我从未使用过.NET3.5Sockets,所以这个答案是一个有根据的猜测 您遇到的问题是,您没有在每次读取时以某种状态存储内容。 所以问题是:
首先
string content=string.Empty代码>
string content=string.Empty代码>
要接收调用ProcessReceive的剩余数据,这是不正确的。您需要使用ReceiveAsync对底层套接字进行另一次读取 我已使用
您可以使用
缓冲区
或缓冲区列表
,但不能同时使用两者如果将缓冲区设置为非空值,并且尝试将BufferList属性设置为非空值,则会引发异常。
因此在此处将BufferList
设置为null
,没有意义,因为Buffer
中的任何一个都不是空的,在这种情况下BufferList
无论如何都是空的,或者Buffer
为null,在这种情况下GetString
将已经抛出ArgumentNullException
。
// You'll need some state object, if you don't already have one
class AsyncServerState
{
public byte[] Buffer = new byte[8192]; // 8K buffer
public StringBuilder Content = new StringBuilder0; // Place to store the content as it's received
public SocketAsyncEventArgs ReadEventArgs = new SocketAsyncEventArgs();
public Socket Client;
}
// You'll need to setup the state where ever you process your connect
// something similar to this.
void Accept_Completed(object sender, SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
Socket client = e.AcceptSocket;
AsyncServerState state = new AsyncServerState();
state.ReadEventArgs.AcceptSocket = client;
state.ReadEventArgs.Completed += new EventHandler( IO_Completed);
state.ReadEventArgs.UserToken = state;
state.Client = client;
state.ReadEventArgs.SetBuffer(state.Buffer, 0, state.Buffer.Length);
if (!client.ReceiveAsync(state.ReadEventArgs))
{
// Call completed synchonously
ProcessReceive(state.ReadEventArgs);
}
}
ProcessAccept(e);
}
private void ProcessReceive(SocketAsyncEventArgs e)
{
var state = e.UserToken as AsyncServerState;
// Check if the remote host closed the connection.
if (e.BytesTransferred > 0)
{
if (e.SocketError == SocketError.Success)
{
// Get the message received from the listener.
sting content = Encoding.ASCII.GetString(state.Buffer, 0, e.BytesTransferred);
// Append the received data to our state
state.Content.Append(content);
// Increment the count of the total bytes receive by the server
Interlocked.Add(ref this.totalBytesRead, bytesTransferred);
if (content.IndexOf(Convert.ToString((char)3)) > -1)
{
// Final Message stored in our state
string finalContent = state.Content.ToString();
return;
}
else
{
// You need to issue another ReceiveAsync, you can't just call ProcessReceive again
if (!state.Client.ReceiveAsync(state.ReadEventArgs))
{
// Call completed synchonously
ProcessReceive(state.ReadEventArgs);
}
}
}
else
{
this.CloseClientSocket(e);
}
}
}