сокеты c#, обрабатывающие несколько клиентов
У меня есть следующий код, который я хочу реализовать как мой сервер. Насколько я понимаю, это асинхронно. и должен разрешать подключения от нескольких клиентов...
public void Start()
{
TcpListener listener = new TcpListener(IPAddress.Any, 10250);
listener.Start();
Console.WriteLine("Listening...");
while (true)
{
IAsyncResult res = listener.BeginAcceptTcpClient(HandleAsyncConnection, listener);
connectionWaitHandle.WaitOne();
}
}
private void HandleAsyncConnection(IAsyncResult res)
{
TcpListener listener = (TcpListener)res.AsyncState;
TcpClient client = listener.EndAcceptTcpClient(res);
connectionWaitHandle.Set();
StringBuilder sb = new StringBuilder();
var data = new byte[client.ReceiveBufferSize];
using (NetworkStream ns = client.GetStream())
{
// Test reply
Byte[] replyData = System.Text.Encoding.ASCII.GetBytes(DateTime.Now.ToString());
ns.Write(replyData, 0, replyData.Length);
ns.Flush();
ns.Close();
}
client.Close();
}
У меня есть тестовое приложение, которое просто стреляет запросы на мой сервер. Как вы можете видеть в коде, сервер просто отвечает своей датой / временем. Тестовое приложение отправляет 20 запросов, которые являются просто тестовыми строками. Для каждого из этих запросов он открывает сокет, отправляет данные на мой сервер, а затем закрывает сокет снова.
это отлично работает с одним тестовым приложением. Однако, если я открою два тестовых приложения, второе не сможет подключиться к серверу. Я думал, потому что я обрабатываю запрос async. и потому, что мое тестовое приложение открывается, а затем закрывает сокет перед каждым вызовом, я могу обрабатывать запросы от нескольких клиентов?
2 ответов
редактировать
при использовании >=.Net4.5, лучше использовать новые сетевые методы, которые затем разрешают принятие async
и await
. Таким образом, было бы лучше следовать примеру, который я привел в этот пост в качестве отправной точки.
Оригинальное Сообщение
в следующем коде показано, как принимать несколько клиентов асинхронно, не отключая новый поток на соединение.
private TcpListener listener;
public void Start()
{
listener = new TcpListener(IPAddress.Any, 10250);
listener.Start();
Console.WriteLine("Listening...");
StartAccept();
}
private void StartAccept()
{
listener.BeginAcceptTcpClient(HandleAsyncConnection, listener);
}
private void HandleAsyncConnection(IAsyncResult res)
{
StartAccept(); //listen for new connections again
TcpClient client = listener.EndAcceptTcpClient(res);
//proceed
}
вы можете использовать этот шаблон для большинства асинхронные операции.
то, как вы это сделали, нет никакой пользы по сравнению с использованием AcceptTcpClient
. Просто цикл и создать новый поток для каждого принятого соединения:
public void Start()
{
TcpListener listener = new TcpListener(IPAddress.Any, 10250);
listener.Start();
Console.WriteLine("Listening...");
while (canRun)
{
var client = listener.AcceptTcpClient();
new Thread(ClientThread).Start(client);
}
}
private void ClientThread(IAsyncResult res)
{
TcpClient client = (TcpClient)res.AsyncState;
StringBuilder sb = new StringBuilder();
var data = new byte[client.ReceiveBufferSize];
using (NetworkStream ns = client.GetStream())
{
// Test reply
Byte[] replyData = System.Text.Encoding.ASCII.GetBytes(DateTime.Now.ToString());
ns.Write(replyData, 0, replyData.Length);
ns.Flush();
ns.Close();
}
client.Close();
}
золотое правило при использовании асинхронных методов является не заблокировать операцию. Блокирование уничтожит цель использования асинхронных операций.
public void Start()
{
TcpListener listener = new TcpListener(IPAddress.Any, 10250);
listener.Start();
Console.WriteLine("Listening...");
listener.BeginAcceptTcpClient(OnAccept, listener);
}
private void OnAccept(IAsyncResult res)
{
TcpListener listener = (TcpListener)res.AsyncState;
TcpClient client = listener.EndAcceptTcpClient(res);
StringBuilder sb = new StringBuilder();
var data = new byte[client.ReceiveBufferSize];
using (NetworkStream ns = client.GetStream())
{
// Test reply
Byte[] replyData = System.Text.Encoding.ASCII.GetBytes(DateTime.Now.ToString());
ns.Write(replyData, 0, replyData.Length);
ns.Flush();
ns.Close();
}
client.Close();
}