c# - 异步/等待套接字连接中的竞争条件

标签 c# sockets async-await

此发送方法会定期失败,因为控制权返回到调用线程,并且在套接字打开时再次调用 Send

我正在使用 Stephen Toub 的类(class):http://blogs.msdn.com/b/pfxteam/archive/2011/12/15/10248293.aspx

这会导致异常:在已连接的套接字上发出连接请求。
确保异步方法不会遭受这种命运的正确方法是什么?基本上,在建立连接之前发送实际上无法完成。

    public async Task Send(byte[] tosend)
    {
        // this code is not correct / not thread safe.
        if (this.socket.Connected)
            await this.StartSending(tosend);
        else
            await StartConnecting(tosend);
    }

    private async Task StartSending(byte[] tosend)
    {
        var args = new SocketAsyncEventArgs();
        args.SetBuffer(tosend, 0, tosend.Length);
        var awaitable = new SocketAwaitable(args);
        await this.socket.SendAsync(awaitable);
    }

    private async Task StartConnecting(byte[] tosend)
    {
        var local = Dns.GetHostEntry(Dns.GetHostName());
        var ep = new IPEndPoint(local.AddressList.First(_ => _.AddressFamily == AddressFamily.InterNetwork), this.port);
        var args = new SocketAsyncEventArgs() { RemoteEndPoint = ep };
        var awaitable = new SocketAwaitable(args);
        await this.socket.ConnectAsync(awaitable);
        await StartSending(tosend);
    }

我的测试只是非常快速地连续调用Send

var sends = arrays.Select(_ => writer.Send(_)).ToArray();
Task.WaitAll(sends);

有时上面的代码工作得很好,并且套接字已连接,socket.Connected '按时'设置为 true。其他时候,对 this.socket.ConnectAsync 的调用会发生多次。

最佳答案

应该等待对 Send 的调用,这样您就可以知道连接已经建立,也可以知道数据正在按顺序发送。这最好通过 foreach 循环来处理,而不是 .Select

foreach (var data in arrays)
    await writer.Send(data);

大概您创建了变量sends,以便您可以对其进行Task.WhenAll。不幸的是,由于您已经发现的原因,这不起作用。您可以使用名为 Connect 的单独方法来解决此问题,该方法异步连接到远程主机,但发送数据。然后你可以这样做:

await writer.Connect();
var sends = arrays.Select(_ => writer.Send(_)).ToArray();

关于c# - 异步/等待套接字连接中的竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29124274/

相关文章:

c# - 以对数刻度显示刻度标签 MS 图表 (log-log)

c# - Fody/Costura 的问题

c# - Xunit Assert.Throws 中的异步 lambda 表达式

c# - 我可以在任务列表完成时生成 IAsyncEnumerable 值吗?

c# - 同步等待一个异步操作,Wait()为什么会在这里卡住程序

c# - 当用户增加 SQL 数据库大小时接收通知

c# - 这是什么语法,将接口(interface)初始化为类数组? (新的 IItemTransform[0])

delphi - 从Windows应用程序向服务应用程序发送大量数据

java - 短信UDP应用

c++ - 套接字通过并发FTP传输接收到错误的数据