- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我习惯了开始/结束 APM 模式,我想将我的套接字服务器更新为 .Net 4.5/async/await。我从 Internet 来源编写了示例代码,但无法正常工作。
我希望所有已连接的客户端在被接受连接(尚未实现..)后被分离到自己的类中。接受所有传入连接的循环在自己的线程中运行。
基本上,Main.cs 是我接受客户端、创建新类 (Client.cs/Session.cs) 进行连接并将接受客户端指向该类的地方。好吧,这就是我打算做的,它不在代码中,目前的主要问题是我对如何处理这个接受序列的了解以及为什么我不能同时连接多个客户端?我希望你能指出我正确的答案。
提前谢谢你。
Form1.cs
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Server
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// Own thread for accepting connections
Main ConnectionLoop = new Main(10);
Thread thread = new Thread(new ThreadStart(ConnectionLoop.PrepareThread));
thread.IsBackground = true;
thread.Start();
}
}
}
Main.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Server
{
public class Main
{
private int m_backLog = 0;
// constructor
public Main(int Backlog)
{
m_backLog = Backlog;
Console.WriteLine("Main class created, backlog: {0}", Backlog);
}
public void PrepareThread()
{
Console.WriteLine("Thread created");
StartAccepting(CancellationToken.None).Wait();
}
private async Task StartAccepting(CancellationToken token)
{
Console.WriteLine("Started listening..");
CancellationTokenSource cts = new CancellationTokenSource();
TcpListener listener = new TcpListener(IPAddress.Any, 6112);
listener.Start();
await AcceptClientsAsync(listener, cts.Token);
// Thread.Sleep(600000);
}
private async Task AcceptClientsAsync(TcpListener listener, CancellationToken token)
{
var clientCounter = 0;
while (!token.IsCancellationRequested)
{
TcpClient client = await listener.AcceptTcpClientAsync().ConfigureAwait(false);
clientCounter++;
Console.WriteLine("Client {0} accepted!", clientCounter);
await EchoAsync(client, clientCounter, token);
}
}
private async Task EchoAsync(TcpClient client, int clientCounter, CancellationToken token)
{
using (client)
{
var buf = new byte[4096]; // buffer for stream
var stream = client.GetStream(); // stream itself
while (!token.IsCancellationRequested)
{
// some conditions we don't know is client connected, lets have timeout
var timeoutTask = Task.Delay(TimeSpan.FromSeconds(15));
var amountReadTask = stream.ReadAsync(buf, 0, buf.Length, token);
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;
}
var amountRead = amountReadTask.Result;
if (amountRead == 0) break; // end of stream
await stream.WriteAsync(buf, 0, amountRead, token).ConfigureAwait(false);
}
}
Console.WriteLine("Client {0} disconnected", clientCounter);
}
}
}
最佳答案
Async 适用于长时间运行的进程,可防止对长时间运行的 I/O 绑定(bind)进程进行不必要的等待。它不提供任何类型的并发。它只是释放了 CPU,所以它不会坐等。
因此,您需要利用 TPL(任务并行库)的其余部分来提供允许并发客户端所需的并发性。这可能意味着一旦连接发生,就为客户端分离出一个任务,并使用该任务来管理客户端。
异步可以通过确保每个客户端不会阻塞一个完整的线程来补充这一点,但异步本身只能帮助您不阻塞,它不提供并发性。
首先,我强烈建议您阅读 MSDN 上有关 TPL 的所有信息。它很多,但它是很好的阅读 Material ,并且会有很大帮助。 https://msdn.microsoft.com/en-us/library/dd460717(v=vs.110).aspx
至于更具体的例子,我可以试试。在您接受客户端的循环中,您将希望在连接客户端后立即获得并行性。这将使您的运行循环返回到接受客户端,并让客户端仍然交互。例如:
private async Task AcceptClientsAsync(TcpListener listener, CancellationToken token)
{
var clientCounter = 0;
while (!token.IsCancellationRequested)
{
TcpClient client = await listener.AcceptTcpClientAsync().ConfigureAwait(false);
clientCounter++;
Console.WriteLine("Client {0} accepted!", clientCounter);
Task.Run(async () => await EchoAsync(client, clientCounter, token), token);
}
}
注意这是伪代码。我没有尝试编译它。但这个概念很扎实。
如果您有大量客户端,您将需要比仅使用 Task.Run 更具体,但对于示例来说它工作正常。它将利用线程池线程来实现并行性。这至少在 100 时工作正常,但之后性能可能会下降。
关于c# - async/await Tcp socket 实现只接受一个连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39150510/
我有一个 forEach循环处理数组中的数据。在该循环中间的某个地方,我必须等待 DOM 元素的更改,获取该更改,处理它,然后才能继续处理数组。 我希望在控制台中看到这个: Preparing "aa
给定以下方法: public async Task DoSomethingAsync() { // do some work await OpenSomeFileAsync();
尝试在 .exports 中运行一个异步函数,获取 Promise,然后在下一个异步函数中使用结果,但由于某种原因,无论等待如何,第二个函数都会在第一个函数之前执行。 销售.js = const sq
谁能解释为什么 c# 5 中的异步函数需要至少有 1 个等待?我找不到明确的理由/解释。 所谓必需,是指当异步函数内部没有任何 await 调用时编译器会发出警告,但不会抛出编译错误。 来自 this
我想用 Mocha 测试异步代码. 我跟着这个教程testing-promises-with-mocha .最后,它说最好的方法是 async/await。 以下是我的代码,我打算将 setTimeo
这个问题在这里已经有了答案: How do yield and await implement flow of control in .NET? (5 个答案) How is resumption
我想在 trait 中编写异步函数,但是因为 async fn in traits 还不被支持,我试图找到等效的方法接口(interface)。这是我在 Rust nightly (2019-01-0
在 node.js 中,我有一个数据库事务,我想在 then 回调中调用一个 async 方法,但我收到错误消息 关键字“等待”已保留。 这是异步 saveImage 函数: const saveIm
我正在包装 AspNet.Identity。但有些事情让我对 TPL 感到困惑。 第一个例子: public virtual async Task RemovePasswordAsync(st
我有三个 showDialog 示例。我认为 _showAlert1 是正确的,但它使用 2 个函数来实现它。 _showAlert2 也有效,但我认为它不正确,因为我认为 showDialog 是异
我正在编写一个应该尽可能快地执行所有异步函数的函数,但是,它们中只有 5 个可以同时运行。 我想使用 Promise.race 来实现,所以实现不是最好的。问题是代码执行不会在 await 处停止。我
在 Scala 和其他编程语言中,可以使用 Futures 和 Await。 (在实际代码中,会使用例如 zip+map 而不是 Await) def b1() = Future { 1 } def
这个问题在这里已经有了答案: At the end of an async method, should I return or await? (2 个回答) 8年前关闭。 我做了一些阅读,并认为我已
我知道这是一个非常开放的问题,我深表歉意。 我可以看到 Await.ready返回 Awaitable.type而 Await.result返回 T但我仍然混淆他们。 两者有什么区别? 一个是阻塞的,
为什么等待者(GetAwaiter - 使类可等待)是结构而不是类。使用类有什么坏处吗? public struct ConfiguredTaskAwaiter : ICriticalNotifyCo
这个问题在这里已经有了答案: Why doesn't Scala's Future have a .get / get(maxDuration) method, forcing us to resor
async/await 链中的所有函数都必须使用 async/await 关键字吗? async function one() { return await fetch(.....); } asy
点击组件的按钮时将执行以下方法。 async onClickButton() { await this.shoppingCartService.add(this.selectedOffer);
它似乎被记录在案的唯一地方是 this issue thread和 the actual specification .但是,删除的原因并没有在我能找到的任何地方发布。 新的推荐方式似乎是await
为什么使用 await 需要将其外部函数声明为 async? 例如,为什么这个 mongoose 语句需要它所在的函数来返回一个 promise? async function middleware(
我是一名优秀的程序员,十分优秀!