Соединение сокета TCP C #, заменяющее возвращаемые данные непреднамеренными символами - PullRequest
0 голосов
/ 23 декабря 2018

Я экспериментирую на системе аутентификации сервер-клиент, и моя цель - отправить несколько деталей, таких как идентификатор Mac, IP-адрес и т. Д. На сервер TCP, затем сервер получит его, проверит базу данных, если указанный адрес присутствует, если он естьон вернет «0» в качестве возвращаемых данных.Затем клиент читает его и запускает функцию OnAuthorized.

Итак, проблема в том, что Клиент отправляет данные, сервер читает их, а затем возвращает 0, но в коде, я вижу

0 \ 0 \ 0 \ 0 \ 0 \ 0 \

вместо «0» На консоли отображается 0, но следующая строка довольно неактивна, поэтому я предполагаю, что ее пробельные символы, но Trim () надо их убирать не так ли?но не делает.Я использовал контрольные точки и проверил возвращаемое значение в HTML Visualizer и увидел один символ 0, но он не отражается на фактической строке.вот код.

Клиент

IPEndPoint IPEndPoint = new IPEndPoint(ServerIP, Constants.SecurityServerPort);
            Client.Connect(IPEndPoint);
            Logger.LogGenericInfo("Socket created to {0}", Client.RemoteEndPoint.ToString());
            byte[] sendmsg = Encoding.ASCII.GetBytes(MsgToSend);
            int Send = Client.Send(sendmsg);
            int Received = Client.Receive(Data);

            if(Data != null)
            {
                ReceivedData = Encoding.ASCII.GetString(Data).Trim(' ');
                Logger.LogGenericInfo(ReceivedData);
            }

            Client.Shutdown(SocketShutdown.Both);
            Client.Close();

Сервер:

IPEndPoint localEndpoint = new IPEndPoint(IPAddress.Any, 7205);
        ConsoleKeyInfo key;
        int count = 0;
        Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        sock.Bind(localEndpoint);
        sock.Listen(5);
        while (true)
        {

            Console.WriteLine("\nWaiting for clients..{0}", count);
            Socket confd = sock.Accept();
            int b = confd.Receive(Buffer);
            data += Encoding.ASCII.GetString(Buffer, 0, b);
            Console.WriteLine("" + data);
            data = null;
            confd.Send(Message);
            Console.WriteLine("\n<< Continue 'y' , Exit 'e'>>");
            key = Console.ReadKey();
            if (key.KeyChar == 'e')
            {
                Console.WriteLine("\nExiting..Handled {0} clients", count);
                confd.Close();
                System.Threading.Thread.Sleep(5000);
                break;
            }
            confd.Close();
            count++;
        }

Данные возврата сервера = private static byte[] Message = Encoding.ASCII.GetBytes("0");

1 Ответ

0 голосов
/ 23 декабря 2018

Клиент получает данные в свой буфер, но вы не используете сохраненное вами значение количества полученных байтов:

        int Received = Client.Receive(Data);

Затем вы превращаете весь буфер в строку, которая будет включатьмного символов NUL (ascii 0), а также ваша нулевая цифра (ascii 48).Если буфер используется повторно, он также повторит старые данные и может представлять угрозу безопасности:

        if(Data != null)
        {
            ReceivedData = Encoding.ASCII.GetString(Data).Trim(' ');

Кстати, if всегда будет истинным.Возможно, вы имеете в виду if(Received > 0)

Затем вы пытаетесь обрезать их, используя обрезку, но вы говорите c # обрезать пробелы (ascii 32), и это не пробел, который загрязняет, это NUL (ascii 0) ..

Было бы лучше сделать то, что вы делаете на стороне сервера, и использовать Received количество байтов для ограничения количества символов, возвращаемых GetString.Вот что вы делаете на стороне сервера:

        int b = confd.Receive(Buffer);
        data += Encoding.ASCII.GetString(Buffer, 0, b);

Вы используете b на сервере.На клиенте вы не используете Получено.Я не совсем уверен, почему вы говорите data +=, так как это добавит ваши текущие данные к предыдущим данным, но, возможно, это преднамеренно

Кстати, пожалуйста, избегайте именования переменных в рамках метода (переменные, которые определяютвнутри тел методов, например int Received, с заглавной буквой в начале. В c # это соглашение предназначено для общедоступных свойств, методов, событий, переменных уровня класса и т. д. Довольно сложно прочитать код, который не следует этим соглашениям, потому чтоэти переменные не определены в том месте, где их имя подразумевает, что они будут определены

Вы также можете столкнуться с проблемами с этим кодом в том, что сервер будет отвечать клиенту только один раз, а затем сделать паузу, пока он ждетдля консольного ввода от вас. Опять же, это может быть преднамеренным, но это кажется маловероятным. Я бы рекомендовал вам перейти на использование асинхронного программирования для получения и обработки данных на стороне сервера, тогда сервер сможет обслуживать несколько клиентов одновременновремя. Прямо сейчас, это будетЯ буду бороться, чтобы сделать это, даже если вы удалите взаимодействие консоли.Несмотря на то, что вы можете сделать этот сервер очень простым, это не идеальное введение в «то, как должны выполняться серверы», чтобы иметь такой «синхронный» способ «читать некоторые данные, выполнять некоторую работу, записывать некоторые данные», потому что первый клиент имеетждать, пока работа сделана, и второй клиент должен ждать, пока первый клиент не уйдет.

Последний пункт (обещание) - есть несколько способов (например, реализации микросервисной архитектуры), встроенных в c #, где весь этот низкоуровневый фейфинг, запись байтов в сокеты и т. Д. Он отнял у нас и сделал очень хорошо Microsoftи все, что нам нужно сделать, это определить службу и имя операции (написав метод с именем этой вещи) и написать код на стороне сервера, который реализует операцию. Затем на стороне клиента мы в основном сообщаем Visual Studio "Я хочу использовать этот сервис », и он записывает весь код на стороне клиента, необходимый для его связывания, поэтому на стороне клиента по существу идет две строки (создание клиента, вызов метода), а на стороне сервера в этом случае около 3 строк (объявление метода, чтение значения, возвращаемое значение ответа) и его многопоточный, асинхронный, работает отлично, не запутанная смесь байтов и кодировок, операций с сокетами, циклы blah

Делать это так, как вы сделали здесьотлично подходит для изучения и оценки нижних работ, но это вродеписать свой собственный драйвер дисплея, а не использовать драйвер Nvidia;нет особого смысла

Простой пример Hello World (примерно такой же, как то, что вы делаете): https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-create-a-basic-wcf-web-http-service

Более подробная информация о сервис-хосте: https://docs.microsoft.com/en-us/dotnet/framework/wcf/hosting-services

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...