我以前使用过 BeginAccept() 和 BeginRead(),但是在 Visual Studio 2012 中我想使用新的异步 (async, await) 功能在我的套接字服务器程序中.
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.
如何完成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() { } } } 推荐答案...因为您如此坚定,所以我整理了一个非常简单的示例,说明如何编写一个回显服务器来帮助您顺利上路.收到的任何内容都会回显给客户端.服务器将保持运行 60 秒.尝试通过本地主机端口 6666 telnet 到它.花点时间了解这里到底发生了什么.
...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 异步功能进行套接字编程
发布评论