代码之家  ›  专栏  ›  技术社区  ›  Doug Null

C#如何使用“await”等待异步客户端套接字的连接[重复]

  •  0
  • Doug Null  · 技术社区  · 7 年前

    我以前用过 BeginAccept() BeginRead() async , await

    我怎样才能完成 AcceptAsync ReceiveAsync 功能?

    using System.Net;
    using System.Net.Sockets;
    
    namespace OfficialServer.Core.Server
    {
        public abstract class CoreServer
        {
            private const int ListenLength = 500;
            private const int ReceiveTimeOut = 30000;
            private const int SendTimeOut = 30000;
            private readonly Socket _socket;
    
            protected CoreServer(int port, string ip = "0.0.0.0")
            {
                _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                _socket.Bind(new IPEndPoint(IPAddress.Parse(ip), port));
                _socket.Listen(ListenLength);
                _socket.ReceiveTimeout = ReceiveTimeOut;
                _socket.SendTimeout = SendTimeOut;
                _socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
                _socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
            }
    
            public void Start()
            {    
            }
        }
    }
    
    0 回复  |  直到 13 年前
        1
  •  59
  •   spender    9 年前

    …因为你很有决心,所以我给你举了一个非常简单的例子来说明如何编写echo服务器来让你上路。接收到的任何信息都会回传给客户。服务器将保持运行60秒。请尝试在本地主机端口6666上对其进行远程登录。花点时间弄清楚这里到底发生了什么。

    void Main()
    {
        CancellationTokenSource cts = new CancellationTokenSource();
        TcpListener listener = new TcpListener(IPAddress.Any, 6666);
        try
        {
            listener.Start();
            //just fire and forget. We break from the "forgotten" async loops
            //in AcceptClientsAsync using a CancellationToken from `cts`
            AcceptClientsAsync(listener, cts.Token);
            Thread.Sleep(60000); //block here to hold open the server
        }
        finally
        {
            cts.Cancel();
            listener.Stop();
        }
    }
    
    async Task AcceptClientsAsync(TcpListener listener, CancellationToken ct)
    {
        var clientCounter = 0;
        while (!ct.IsCancellationRequested)
        {
            TcpClient client = await listener.AcceptTcpClientAsync()
                                                .ConfigureAwait(false);
            clientCounter++;
            //once again, just fire and forget, and use the CancellationToken
            //to signal to the "forgotten" async invocation.
            EchoAsync(client, clientCounter, ct);
        }
    
    }
    async Task EchoAsync(TcpClient client,
                         int clientIndex,
                         CancellationToken ct)
    {
        Console.WriteLine("New client ({0}) connected", clientIndex);
        using (client)
        {
            var buf = new byte[4096];
            var stream = client.GetStream();
            while (!ct.IsCancellationRequested)
            {
                //under some circumstances, it's not possible to detect
                //a client disconnecting if there's no data being sent
                //so it's a good idea to give them a timeout to ensure that 
                //we clean them up.
                var timeoutTask = Task.Delay(TimeSpan.FromSeconds(15));
                var amountReadTask = stream.ReadAsync(buf, 0, buf.Length, ct);
                var completedTask = await Task.WhenAny(timeoutTask, amountReadTask)
                                              .ConfigureAwait(false);
                if (completedTask == timeoutTask)
                {
                    var msg = Encoding.ASCII.GetBytes("Client timed out");
                    await stream.WriteAsync(msg, 0, msg.Length);
                    break;
                }
                //now we know that the amountTask is complete so
                //we can ask for its Result without blocking
                var amountRead = amountReadTask.Result;
                if (amountRead == 0) break; //end of stream.
                await stream.WriteAsync(buf, 0, amountRead, ct)
                            .ConfigureAwait(false);
            }
        }
        Console.WriteLine("Client ({0}) disconnected", clientIndex);
    }
    
        2
  •  15
  •   Konstantin Savelev Stephen Cleary    6 年前

    TaskFactory.FromAsync 包装 Begin / End async -准备行动。

    awaitable Socket 在他的博客上 *Async TPL Dataflow 创建一个完整的 异步 插座 组件。

    推荐文章