C# 异步/等待套接字接收数据问题

C# 异步/等待套接字接收数据问题,c#,sockets,asynchronous,async-await,task,C#,Sockets,Asynchronous,Async Await,Task,这是从套接字读取数据的好方法吗 public class StateObject : IDisposable { private const int _bufferSize = 1024; public byte[] Buffer { get; } = new byte[_bufferSize]; public int BufferSize { get; } = _bufferSize; public MemoryStream MsStream { get; }

这是从
套接字
读取数据的好方法吗

public class StateObject : IDisposable
{
    private const int _bufferSize = 1024;
    public byte[] Buffer { get; } = new byte[_bufferSize];
    public int BufferSize { get; } = _bufferSize;
    public MemoryStream MsStream { get; }

    public EnhStateObject()
    {
        MsStream = new MemoryStream();
    }

    public void Dispose()
    {
        MsStream.Dispose();
    }
}

public async static Task<int> ReceiveAsync(this Socket client, StateObject state)
{
    var task = await await Task<int>.Factory.FromAsync(
    (cb, s) => client.BeginReceive(state.Buffer, 0, state.BufferSize, SocketFlags.None, cb, s),
    client.EndReceive, null).ContinueWith(t =>
    {
        state.MsStream.Write(state.Buffer, 0, t.Result);
        return t;
    });

    if (task == state.BufferSize) await client.ReceiveAsync(state);

    return task;
}
公共类StateObject:IDisposable
{
私有常量int_bufferSize=1024;
公共字节[]缓冲区{get;}=新字节[_bufferSize];
public int BufferSize{get;}=\u BufferSize;
公共内存流MsStream{get;}
公共对象()
{
MsStream=新内存流();
}
公共空间处置()
{
MsStream.Dispose();
}
}
公共异步静态任务ReceiveAsync(此套接字客户端,StateObject状态)
{
var task=wait wait task.Factory.fromsync(
(cb,s)=>client.BeginReceive(state.Buffer,0,state.BufferSize,SocketFlags.None,cb,s),
client.EndReceive,空)。ContinueWith(t=>
{
state.MsStream.Write(state.Buffer,0,t.Result);
返回t;
});
if(task==state.BufferSize)等待client.ReceiveAsync(state);
返回任务;
}
我的意思是,在对象外部进行传输,并通过递归调用将接收到的信息存储在对象中


或者有没有更优雅的方法使用相同的
fromsync
包装器来实现这一点?

没有,这不是从套接字读取数据的好方法。你在这里重新发明轮子。我不知道为什么您需要使用低级的
Socket
API,但是,您不需要

相反,请将您的
套接字
包装在调用站点的
网络流中,如下所示:

Socket socket = ....;
Stream stream = new NetworkStream(socket);
然后,您可以像预期的那样使用
ReadAsync()
读取数据(好处是:没有状态对象可以传递,您可以在测试中使用标准
MemoryStream
模拟流)


如果您使用的是Tcp,我建议您使用API而不是直接使用套接字。

不,这不是从套接字读取数据的好方法。你在这里重新发明轮子。我不知道为什么您需要使用低级的
Socket
API,但是,您不需要

相反,请将您的
套接字
包装在调用站点的
网络流中,如下所示:

Socket socket = ....;
Stream stream = new NetworkStream(socket);
然后,您可以像预期的那样使用
ReadAsync()
读取数据(好处是:没有状态对象可以传递,您可以在测试中使用标准
MemoryStream
模拟流)


如果您使用的是Tcp,我建议您使用API,而不是直接使用套接字。

如果这样做有效,那么它可能更适合于代码审查。不过,可能需要添加更多细节(例如,
StateObject
的定义可能会有所帮助)<代码>等待等待
看起来可疑。我已经更新了帖子。关于
StateObject
没有什么特别的
wait-wait
同意,这可能更容易:在
Task.Factory.fromsync
之前删除一个
wait
,然后从
继续返回
t.Result
TcpClient
对于客户端来说是一个很好的选择。我的客户端在
.net4
上运行(而不是服务器端,witch在
.net4.6.1
上运行),并且无法使用
ReadAsync
,AFAIK。因此,我希望编写可以在两个平台上使用的代码。如果这样做有效,那么它可能更适合于代码审查。不过,可能需要添加更多细节(例如,
StateObject
的定义可能会有所帮助)<代码>等待等待
看起来可疑。我已经更新了帖子。关于
StateObject
没有什么特别的
wait-wait
同意,这可能更容易:在
Task.Factory.fromsync
之前删除一个
wait
,然后从
继续返回
t.Result
TcpClient
对于客户端来说是一个很好的选择。我的客户端在
.net4
上运行(而不是服务器端,witch在
.net4.6.1
上运行),并且无法使用
ReadAsync
,AFAIK。因此,我希望编写可以在这两种平台上使用的代码。Thnxs,这对我的服务器端
.net4.6.1
很有好处。使用
.net4
的客户端怎么样?如何制作APM而不沉沦到
Sockets
API的层次?在问题中提及您的需求是一个好主意,其中包括您正在使用的.NET framework。NET4没有
ReadAsync
,但它仍然有
NetworkStream
。不幸的是,在那个版本中,似乎没有一种方法可以在这个流上使用异步读取,而不使用旧的
开始
/
结束
方法来满足需求,我将在将来使用它。Thnxs,这对我的服务器端
.net4.6.1
很有好处。使用
.net4
的客户端怎么样?如何制作APM而不沉沦到
Sockets
API的层次?在问题中提及您的需求是一个好主意,其中包括您正在使用的.NET framework。NET4没有
ReadAsync
,但它仍然有
NetworkStream
。不幸的是,在该版本中,似乎没有一种方法可以在该流上使用异步读取,而不使用旧的
开始
/
结束
方法来满足需求,我将在将来使用它。