Ila*_*321 6 c# tcp tcplistener tcpclient
我一直在制作服务器.我在方法中使用TcpListener.AcceptTcpClientAsync()async,但我不知道如何实际使它工作.我的代码现在是:
private static async void StartServer()
{
Console.WriteLine("S: Server started on port {0}", WebVars.ServerPort);
var listener = new TcpListener(WebVars.LocalIp, WebVars.ServerPort);
listener.Start();
var client = await listener.AcceptTcpClientAsync();
}
Run Code Online (Sandbox Code Playgroud)
我该如何处理客户?我只是继续编码,它会自动创建相同方法的新线程,还是我需要做一些魔术方法来为我做?
编辑:当前代码:
private static Task HandleClientAsync(TcpClient client)
{
var stream = client.GetStream();
// do stuff
}
/// <summary>
/// Method to be used on seperate thread.
/// </summary>
private static async void RunServerAsync()
{
while (true)
{
Console.WriteLine("S: Server started on port {0}", WebVars.ServerPort);
var listener = new TcpListener(WebVars.LocalIp, WebVars.ServerPort);
listener.Start();
var client = await listener.AcceptTcpClientAsync();
await HandleClientAsync(client);
}
}
Run Code Online (Sandbox Code Playgroud)
// 简而言之,所有功劳都应该归功于 c# 7.0 (Joseph Albahari & Ben Albahari)
async void RunServerAsync()
{
var listner = new TcpListener(IPAddress.Any, 9999);
listner.Start();
try
{
while (true)
await Accept(await listner.AcceptTcpClientAsync());
}
finally { listner.Stop(); }
}
const int packet_length = 2; // user defined packet length
async Task Accept(TcpClient client)
{
await Task.Yield();
try
{
using(client)
using(NetworkStream n = client.GetStream())
{
byte[] data = new byte[packet_length];
int bytesRead = 0;
int chunkSize = 1;
while (bytesRead < data.Length && chunkSize > 0)
bytesRead += chunkSize =
await n.ReadAsync(data, bytesRead, data.Length - bytesRead);
// get data
string str = Encoding.Default.GetString(data);
Console.WriteLine("[server] received : {0}", str);
// To do
// ...
// send the result to client
string send_str = "server_send_test";
byte[] send_data = Encoding.ASCII.GetBytes(send_str);
await n.WriteAsync(send_data, 0, send_data.Length);
}
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Run Code Online (Sandbox Code Playgroud)
没有什么可以神奇地为你创建专用线程,虽然有一些用于IO完成的线程可以发挥作用,特别是如果你没有需要返回的同步上下文.
您应该决定是否希望您的StartServer方法在接受单个连接时实际完成,或者在您被告知关闭之前保持循环.
无论哪种方式,您显然需要决定如何处理客户端.您可以启动新线程并使用同步方法,也可以使用异步IO来处理同一线程中的所有内容.例如,要将传入数据转储到文件:
private Task HandleClientAsync(TcpClient client)
{
// Note: this uses a *synchronous* call to create the file; not ideal.
using (var output = File.Create("client.data"))
{
using (var input = client.GetStream())
{
// Could use CopyToAsync... this is just demo code really.
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = await input.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
await output.WriteAsync(buffer, 0, bytesRead);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
(这假设客户端只是在完成数据写入时终止连接.)除了File.Create调用之外,这都是异步的 - 因此不需要为它创建单独的线程.
当然,这只是一个例子 - 真正的连接处理通常会更复杂.如果您的实际处理需要更多计算密集型,那么您可能需要考虑使用Task.Run线程池...这样它就不会干扰接受更多连接.
| 归档时间: |
|
| 查看次数: |
12554 次 |
| 最近记录: |