Получение сообщений и отправка сообщений через NetworkStream Клиенту - PullRequest
0 голосов
/ 30 марта 2020

У меня есть вопрос об отправке и получении сообщений с сервера TCPListener клиенту через сетевой поток в C#. Прямо сейчас мой экземпляр TCPListener может получить одно сообщение от клиента и записать его на консоль сервера, а также принять одну входную строку и отправить ее обратно клиенту. Но я хотел бы sh улучшить функцию, чтобы принимать несколько последовательных сообщений от клиента и отправлять несколько последовательных ответов обратно клиенту. Есть ли у кого-нибудь указатели, если функции ReadAsyn c и WriteAsyn c NetworkStream могут обрабатывать получение нескольких последовательных сообщений или отправку нескольких последовательных сообщений, и если есть лучший метод для достижения этой цели? Кроме того, поскольку функция Console.ReadLine будет блокировать в случае, если сервер никогда не получит никакого пользовательского ввода от ReadLine (и не будет нажата ни одна клавиша Enter), есть ли способ проверить, есть ли дополнительный ввод пользователя с клавиатуры? Таким образом, я мог попытаться выполнить команды отправки сообщения, только если сервер получил какой-либо консольный ввод от пользователя и мог продолжать получать клиентские сообщения в противном случае.

   public static async Task getMessage(TcpListener server)
      {
            byte[] bytes = new byte[256];
            using (var theStream = await server.AcceptTcpClientAsync())
            {
                using (var tcpStream = theStream.GetStream())
                {

                    await tcpStream.ReadAsync(bytes, 0, bytes.Length);
                    var msg = Encoding.UTF8.GetString(bytes);
                    Console.WriteLine(msg);
                    var payload = Console.ReadLine();
                    var bytes2 = Encoding.UTF8.GetBytes(payload);
                    await tcpStream.WriteAsync(bytes2, 0, bytes2.Length);
                }

           }

      } 

1 Ответ

0 голосов
/ 30 марта 2020

Интересно видеть реализацию сервера, предназначенную только для одного клиента!

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

Я пытался разместить комментарии в источнике, чтобы он сам себя объяснил.

Но критической точкой является объявление экземпляров TcpClient и NetworkStream как stati c переменных, так что основной поток (поток, который читает из консоли и отправляет полезную нагрузку клиенту) может получить к ним доступ

Надеюсь, это поможет.

public static async Task getMessage(TcpListener server)
{
    byte[] bytes = new byte[256];
    using (theStream = await server.AcceptTcpClientAsync())
    {
        using (tcpStream = theStream.GetStream())
        {
            // We are using an infinite loop which ends when zero bytes have been received.
            // Receiving zero bytes means the transmission is over (client disconnected)
            while (await tcpStream.ReadAsync(bytes, 0, bytes.Length) > 0)
            {
                var msg = Encoding.UTF8.GetString(bytes);
                Console.WriteLine(msg);
            }
            Console.WriteLine("Client has disconnected");
        }
    }
}

/// <summary>
/// Transmists the payload to the client
/// </summary>
/// <param name="payload">The payload to transmit to the client</param>
/// <returns></returns>
static async Task Transmit(string payload)
{
    var bytes2 = Encoding.UTF8.GetBytes(payload);
    await tcpStream.WriteAsync(bytes2, 0, bytes2.Length);
}

// We are declaring the TcpClient and NetworkStream as static variables
// to be able to access them from all the threads.
private static TcpClient theStream;
public static NetworkStream tcpStream;

static void Main(string[] args)
{
    TcpListener server = new TcpListener(IPAddress.Loopback, 9876);
    server.Start();

    // Start the task getMessage() to accept a client and receive
    Task.Run(() => getMessage(server));

    string payload;
    while ((payload = Console.ReadLine()) != "exit")
    {
        // Check if the client has connected.
        if (tcpStream != null)
        {
            // Check if they are still connected
            if (theStream.Client.Connected)
            {
                Task.Run(() => Transmit(payload));
            }
            else
            {
                Console.WriteLine("the client connection is lost");
                break;
            }
        }
        else
        {
            Console.WriteLine("The client has not connected yet.");
        }
    }

    Console.WriteLine("Stopping the server");
    server.Stop();
}
...