使用.NET 4.5异步功能的Socket编程 [英] Using .Net 4.5 Async Feature for Socket Programming

查看:590
本文介绍了使用.NET 4.5异步功能的Socket编程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经previously使用 BeginAccept()的BeginRead(),但与Visual Studio 2012我想利用新的异步的(异步等待)在我的socket服务器程序功能。

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

 使用System.Net;
使用的System.Net.Sockets;命名空间OfficialServer.Core.Server
{
    公共抽象类CoreServer
    {
        私人const int的ListenLength = 500;
        私人const int的ReceiveTimeOut = 30000;
        私人const int的的SendTimeout = 30000;
        私人只读插座_socket;        保护CoreServer(INT口,串IP =0.0.0.0)
        {
            _socket =新的Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
            _socket.Bind(新IPEndPoint(IPAddress.Parse(IP),端口));
            _socket.Listen(ListenLength);
            _socket.ReceiveTimeout = ReceiveTimeOut;
            _socket.SendTimeout =的SendTimeout;
            _socket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.KeepAlive,真正的);
            _socket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.DontLinger,真正的);
        }        公共无效启动()
        {
        }
    }
}


解决方案

@Danial,因为你这么坚决,我放在一起的怎么写回声服务器,让你用自己的方式一个很简单的例子。收到任何被回显到客户端。服务器将保持运行60秒。尝试远程登录到它在本地主机端口6666花时间准确了解是怎么回事。

 无效的主要()
{
    CancellationTokenSource CTS =新CancellationTokenSource();
    监听器的TcpListener =新的TcpListener(IPAddress.Any,6666);
    尝试
    {
        listener.Start();
        //刚刚发射后不管。我们从被遗忘的异步打破循环
        //在AcceptClientsAsync使用的CancellationToken从`cts`
        AcceptClientsAsync(监听器,cts.Token);
        Thread.sleep代码(60000); //阻止这里举行公开服务器
    }
    最后
    {
        cts.Cancel();
        listener.Stop();
    }
}异步任务AcceptClientsAsync(的TcpListener监听器,CT的CancellationToken)
{
    变种clientCounter = 0;
    而(!ct.IsCancellationRequested)
    {
        TcpClient的客户端=等待listener.AcceptTcpClientAsync()
                                            .ConfigureAwait(假);
        clientCounter ++;
        //再次,刚刚火和忘记,并且使用的CancellationToken
        //信号的被遗忘的异步调用。
        EchoAsync(客户端,clientCounter,CT);
    }}
异步任务EchoAsync(TcpClient的客户端,
                     INT clientIndex,
                     的CancellationToken克拉)
{
    Console.WriteLine(,clientIndex连接新的客户端({0}));
    使用(客户端)
    {
        VAR BUF =新的字节[4096];
        VAR流= client.GetStream();
        而(!ct.IsCancellationRequested)
        {
            //在某些情况下,这是不可能的检测
            //客户端断开,如果有发送任何数据
            //所以这是一个好主意,给他们一个超时,以确保
            //我们清除它们。
            变种timeoutTask = Task.Delay(TimeSpan.FromSeconds(15));
            变种amountReadTask = stream.ReadAsync(BUF,0,buf.Length,CT);
            VAR completedTask =等待Task.WhenAny(timeoutTask,amountReadTask)
                                          .ConfigureAwait(假);
            如果(completedTask == timeoutTask)
            {
                VAR味精= Encoding.ASCII.GetBytes(客户端超时);
                等待stream.WriteAsync(味精,0,msg.Length);
                打破;
            }
            //现在我们知道amountTask完成如此
            //我们可以要求其结果不阻塞
            VAR amountRead = amountReadTask.Result;
            如果(amountRead == 0)打破; //流的末尾。
            等待stream.WriteAsync(BUF,0,amountRead,CT)
                        .ConfigureAwait(假);
        }
    }
    Console.WriteLine(客户端({0})断开,clientIndex);
}

I've previously used BeginAccept() and BeginRead(), but with Visual Studio 2012 I want to make use of the new asynchronous (async, await) features in my socket server program.

How can I complete the AcceptAsync and ReceiveAsync functions?

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()
        {    
        }
    }
}

解决方案

@Danial, because you're so determined, I put together a very simple example of how to write an echo server to get you on your way. Anything received gets echoed back to the client. The server will stay running for 60s. Try telnetting to it on localhost port 6666. Take time to understand exactly what's going on here.

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);
}

这篇关于使用.NET 4.5异步功能的Socket编程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆