Работа на клиентском сервере с использованием сокетов и tcp \ ip в C# - PullRequest
0 голосов
/ 04 февраля 2020

Я работаю над получением клиент-серверных данных. Я могу получать данные с сервера, который является моим счетчиком. Код ниже

listner = new TcpListener(new IPEndPoint(IPAddress.Any, port));
        Console.WriteLine("Listening...");
        listner.Start();
        while (true)
        {
            try
            {
                //---incoming client connected---
                TcpClient client = listner.AcceptTcpClient();

                //---get the incoming data through a network stream---
                NetworkStream nwStream = client.GetStream();
                byte[] buffer = new byte[client.ReceiveBufferSize];

                //---read incoming stream---
                int bytesRead = nwStream.Read(buffer, 0, client.ReceiveBufferSize);

                //---convert the data received into a string---
                string dataReceived = BitConverter.ToString(buffer, 0, bytesRead);
                //Encoding.ASCII.GetString(buffer, 0, bytesRead);
                //Console.WriteLine("Received : " + dataReceived);
                //MessageBox.Show("Data Received", dataReceived);
                //---write back the text to the client---
                //Console.WriteLine("Sending back : " + dataReceived);
                //nwStream.Write(buffer, 0, bytesRead);
                client.Close();
            }
            catch (Exception ex)
            {

            }

Используя вышеуказанный код, я могу получить данные. Но я хочу выполнить следующее

  1. Сохранение прослушивания на порту
  2. Во время прослушивания я хочу отправить несколько байтов на сервер (метр)
  3. Получить ответ с сервера после отправки некоторых данных.

Я знаю, что существует множество клиент-серверных обучающих программ, но они имеют отдельную реализацию сервера и клиента. Я просто хочу справиться с клиентом (моим программным обеспечением). Я также пытался с Пример асинхронного сокета сервера .

Любая помощь будет принята с благодарностью.

1 Ответ

0 голосов
/ 05 февраля 2020

Ваш сервер должен постоянно прослушивать соединения от клиентов. Каждый раз, когда он получает соединение, вы получаете от ОС новый TcpClient для обработки этого соединения. TcpClient, который вы получаете от ОС, иногда называется Child TcpClient , потому что он создается портом прослушивания. Но он функционально такой же, как и любой другой сокет.

Этого очень легко достичь с помощью шаблона асинхронного / ожидающего выполнения.

Сначала вам нужен слушатель, который ожидает соединения, каждый раз, когда он получает соединение это передает это другой задаче, которая обрабатывает дочерний TcpClient. Например,

static async Task StartTcpServerAsync()
{
    var tcpListener = new TcpListener(new IPEndPoint(IPAddress.Any, 9999));
    tcpListener.Start();

    while (true)
    {
        var tcpClient = await tcpListener.AcceptTcpClientAsync();

        // Fire and forget the Child connection
        _ = StartChildTcpClientAsync(tcpClient);
    }
}

В приведенном выше коде котельной пластины мы полностью забываем о задаче ChildTcpClient. Вы можете или не хотите этого. Если вы делаете задачу полностью самодостаточной (как эта демонстрация), тогда главной задаче, возможно, никогда не потребуется знать, завершена она или нет. Но если вам необходимо обеспечить обратную связь между Задачей ChildTcpClient и основной задачей, вам потребуется предоставить дополнительный код для управления этим, и вы начнете с хранения Задачи, возвращенной из StartChildTcpClientAsync(tcpClient);, где вы сможете наблюдать Это. Вы можете использовать Task.Run() здесь, но это не обязательно в консольном приложении.

Теперь, когда у вас есть задача слушателя, вам нужна задача ChildTcpClient, например:

static async Task StartChildTcpClientAsync(TcpClient tcpClient)
{
    Console.WriteLine($"Connection received from: {tcpClient.Client.RemoteEndPoint.ToString()}");

    using var stream = tcpClient.GetStream();
    var buffer = new byte[1024];
    while (true)
    {
        var bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
        await stream.WriteAsync(buffer, 0, bytesRead);
    }
}

Это очень простой клиент эхо Tcp. У него нет управления потоком данных и нет обработки ошибок, задача будет просто сидеть и ждать, пока клиент отправит некоторые данные, даже после того, как клиент отключился. Эта задача просто «ждет» бесконечности (или пока не произойдет исключение), поэтому вам нужно добавить сюда некоторый код для управления клиентом, проверить, что клиент все еще подключен, et c et c

Для того, чтобы собрать все это вместе, вам просто понадобится такой основной код:

static async Task Main(string[] args)
{
    await StartTcpServerAsync();
    // Will never exit unless tcpListener.AcceptTcpClientAsync();
    // throws an exception
}

И все, у вас есть консольное приложение, которое ожидает подключения бесконечного числа клиентов, и каждый раз, когда это происходит, это своя задача по работе с IO.

...