В простой клиент-серверной программе на C # tcp я посылаю 5 байтов, сервер видит более 400 000.Что происходит? - PullRequest
0 голосов
/ 24 января 2019

Я пытаюсь проработать основы простого tcp клиент / сервера, чтобы я мог внедрить систему уведомлений, которая будет работать практически где угодно и позволять приложениям, подобным «демонам», взаимодействовать.Одним из клиентов может быть монитор, который просматривает сообщения и показывает состояние всех сбросов и координирует их, например, приостанавливая один или несколько, просматривая, сколько файлов было обработано, каково состояние базы данных и т. Д.Для начала мне нужен очень простой сервер, который ждет сообщений от клиентов и передает их другим клиентам.Вот моя настоящая попытка на сервере (на примере http://csharp.net -informations.com / communications / csharp-chat-server.htm ).

using System;
using System.Threading;
using System.Net.Sockets;
using System.Text;
using System.Collections;

namespace erc.bre
{
    class NotificationServer
    {
        public static Hashtable clientsList = new Hashtable();

        static void Main(string[] args)
        {
            System.Net.IPAddress addr = System.Net.IPAddress.Parse("127.0.0.1");
            TcpListener serverSocket = new TcpListener(addr, 1025);
            TcpClient clientSocket = default(TcpClient);
            int counter = 0;

            serverSocket.Start();
            Console.WriteLine("Chat Server Started ....");
            counter = 0;
            while ((true))
            {
                counter += 1;
                clientSocket = serverSocket.AcceptTcpClient();

                byte[] bytesFrom = new byte[10025];
                clientSocket.ReceiveBufferSize = bytesFrom.Length; // added
                string dataFromClient = null;

                NetworkStream networkStream = clientSocket.GetStream();
             //   Console.WriteLine("Bytes received: {0}", (int)clientSocket.ReceiveBufferSize);
                networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
                dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
                dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));

                clientsList.Add(dataFromClient, clientSocket);

                broadcast(dataFromClient + " Joined ", dataFromClient, false);

                Console.WriteLine(dataFromClient + " Joined chat room ");
                handleClinet client = new handleClinet();
                client.startClient(clientSocket, dataFromClient, clientsList);
            }

            clientSocket.Close();
            serverSocket.Stop();
            Console.WriteLine("exit");
            Console.ReadLine();
        }

        public static void broadcast(string msg, string uName, bool flag)
        {
            foreach (DictionaryEntry Item in clientsList)
            {
                TcpClient broadcastSocket;
                broadcastSocket = (TcpClient)Item.Value;
                NetworkStream broadcastStream = broadcastSocket.GetStream();
                Byte[] broadcastBytes = null;

                if (flag == true)
                {
                    broadcastBytes = Encoding.ASCII.GetBytes(uName + " says : " + msg);
                }
                else
                {
                    broadcastBytes = Encoding.ASCII.GetBytes(msg);
                }

                broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                broadcastStream.Flush();
            }
        }  //end broadcast function
    }//end Main class


    public class handleClinet
    {
        TcpClient clientSocket;
        string clNo;
        Hashtable clientsList;

        public void startClient(TcpClient inClientSocket, string clineNo, Hashtable cList)
        {
            this.clientSocket = inClientSocket;
            this.clientSocket.ReceiveBufferSize = 10025; // added
            this.clNo = clineNo;
            this.clientsList = cList;
            Thread ctThread = new Thread(doChat);
            ctThread.Start();
        }

        private void doChat()
        {
            int requestCount = 0;
            byte[] bytesFrom = new byte[10025];
            string dataFromClient = null;
            Byte[] sendBytes = null;
            string serverResponse = null;
            string rCount = null;
            requestCount = 0;

            while ((true))
            {
                try
                {
                    requestCount = requestCount + 1;
                    NetworkStream networkStream = clientSocket.GetStream();
                    networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
                    dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
                    dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
                    Console.WriteLine("From client - " + clNo + " : " + dataFromClient);
                    rCount = Convert.ToString(requestCount);

                    NotificationServer.broadcast(dataFromClient, clNo, true);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
            }//end while
        }//end doChat
    } //end class handleClinet
}//end namespace

Вы заметитеConsole.WriteLine, где я распечатываю количество полученных байтов.Я добавил это, когда получал исключение в следующем утверждении, что размер был вне диапазона.Это печатает число как 408 000 байтов.

Вот клиентская программа, немного измененная, потому что в моей версии VisualStudio 2017 для Mac я ничего не могу получить с помощью Windows Forms, чтобы даже создать проект в соответствии с примером.Так как я собираюсь поместить код в веб-приложение, как только разберусь в механике, я просто пытаюсь, чтобы клиент ввел свой идентификатор, затем набрал строку, чтобы сервер взял ее и ретранслировал.Другие клиенты будут делать то же самое из командной строки (по одному для каждого нового клиента).В настоящее время он принимает идентификатор пользователя и отправляет его.Я посылаю «Джон», и кажется, что он посылает «Джон $» в виде 5 байтов.

using System;
using System.Text;
using System.Net.Sockets;
using System.Threading;

namespace erc.bre
{
    public class NotificationClient
    {
        System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
        NetworkStream serverStream = default(NetworkStream);
        string readData = null;
        string display = "";
        string userName = "";
        string message = "";
        bool needsInvocation = true;
        static NotificationClient nc = new NotificationClient();

        public NotificationClient()
        {
        }

        public static int Main(string[] args)
        {
            nc.msg();
            return 0;
        }

        private void sendUserJoined()
        {
            byte[] outStream = System.Text.Encoding.ASCII.GetBytes(message + "$");
            serverStream.Write(outStream, 0, outStream.Length);
            serverStream.Flush();
        }

        private void InputReceived()
        {
            readData = "Conected to Chat Server ...";
            msg();
            clientSocket.Connect("127.0.0.1", 1025);
            serverStream = clientSocket.GetStream();

            byte[] outStream = System.Text.Encoding.ASCII.GetBytes(userName + "$");
            Console.WriteLine("Sending {0} bytes as '{1}'", outStream.Length, System.Text.Encoding.Default.GetString(outStream);
            serverStream.Write(outStream, 0, outStream.Length);
            serverStream.Flush();

            Thread ctThread = new Thread(getMessage);
            ctThread.Start();
        }

        private void getMessage()
        {
            while (true)
            {
                serverStream = clientSocket.GetStream();
                int buffSize = 0;
                byte[] inStream = new byte[10025];
                buffSize = clientSocket.ReceiveBufferSize;
                serverStream.Read(inStream, 0, buffSize);
                string returndata = System.Text.Encoding.ASCII.GetString(inStream);
                readData = "" + returndata;
                msg();
            }
        }

        private void msg()
        {
            if (needsInvocation)
            {
                needsInvocation = false;
                Console.Out.WriteLine("Starting Client");
                Console.Out.WriteLine("Input your callerID: ");
                nc.userName = nc.ReadLine();
                nc.InputReceived();
                nc.sendUserJoined();
                nc.getMessage();
                return;
            }
            display = display + Environment.NewLine + " >> " + readData;
            Console.Out.WriteLine(display);
        }

        private string ReadLine()
        {
            string line = "";
            char ch;
            Console.WriteLine("Enter text when desired, 'enter' to end");
            do
            {
                int x = Console.Read();
                try
                {
                    ch = Convert.ToChar(x);
                    if (ch == 0x0a)
                    {
                        return line;
                    }
                }
                catch (OverflowException e)
                {
                    Console.WriteLine("{0} Value read = {1}.", e.Message, x);
                    ch = ' ';
                }
                line += ch;
            } while (ch != 0x0a);
            return line;
        }

    }
}

Консоль сервера показывает:

Сервер чата запущен .... Получено байт: 408300

Необработанное исключение: System.ArgumentOutOfRangeException: указанный аргумент вышел издиапазон допустимых значений.Имя параметра: размер в System.Net.Sockets.NetworkStream.Read (буфер Byte [], смещение Int32, размер Int32) в ConsoleApplication1.NotificationServer.Main (аргументы String []) в / Users / woo / Projects / erc-caml /bre / NotificationServer / NotificationServer.cs: строка 33 bash: строка 1: 45360 Прерывание прерывания: 6 "/ usr / local / share / dotnet / dotnet" "/ Пользователи / woo / Проекты / erc-caml / bre / NotificationServer / bin /Отладка / netcoreapp2.1 / NotificationServer.dll "

На консоли клиента отображается:

Запуск клиента Введите свой идентификатор вызывающего абонента: при желании введите текст, введите 'enter' в конец John

Подключен к серверу чата ... Отправка 5 байтов в виде 'John $'

Необработанное исключение: Необработанное Исключение: System.ArgumentOutOfRangeException: указанный аргумент находится вне диапазонадействительных значений.Имя параметра: размер в System.Net.Sockets.NetworkStream.Read (буфер Byte [], смещение Int32, размер Int32) в erc.bre.NotificationClient.getMessage () в / Users / woo / Projects / erc-caml / bre /NotificationMonitor / NotificationClient.cs: строка 60 в erc.bre.NotificationClient.msg () в /Users/woo/Projects/erc-caml/bre/NotificationMonitor/NotificationClient.cs:line 77

Почему сервервидя более 400 000 байтов?Это внутреннее поглощение материала, пока оно ожидает сообщения?Номер выглядит одинаково, независимо от того, как долго я жду, кстати.

1 Ответ

0 голосов
/ 24 января 2019
clientSocket.ReceiveBufferSize

Возвращает размер буфера приема, который не совпадает с количеством принятых байтов.Используйте метод Read вашего сетевого потока ( serverStream ) и проверьте его результат, который сообщит вам, сколько байтов было прочитано.

См. NetworkStream.Read(Байт [], Int32, Int32) Метод и TcpClient.GetStream для получения дополнительной информации.

...