сокеты c # для работы с несколькими клиентами - PullRequest
9 голосов
/ 21 апреля 2011

У меня есть следующий код, который я хочу реализовать в качестве моего сервера.Как я понимаю, это асинхронно.и должен разрешать подключения от нескольких клиентов ...

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 запросов, которые являются просто тестовыми строками.Для каждого из этих запросов он открывает сокет, отправляет данные на мой сервер, а затем снова закрывает сокет.

Это прекрасно работает с одним запущенным тестовым приложением.Однако, если я открою два тестовых приложения, второе не сможет подключиться к серверу.Я думал, потому что я обрабатываю запрос асинхронно.и поскольку мое тестовое приложение открывается, то закрывает сокет перед каждым вызовом, чтобы я мог обрабатывать запросы от нескольких клиентов?

Ответы [ 2 ]

19 голосов
/ 21 апреля 2011

Редактировать

При использовании> =. 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

}

Этот шаблон можно использовать для большинства асинхронных операций.

1 голос
/ 21 апреля 2011

То, как вы это сделали, не дает никакой выгоды по сравнению с использованием 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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...