0 / 0 / 0
Регистрация: 06.04.2014
Сообщений: 6
1

Передача данных от клиента к серверу

19.11.2016, 20:04. Показов 1780. Ответов 7
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем привет!
Возникла потребность передавать данные по симметрично-шифрованному соединению.
Клиент передает данные(в данном случае число double), сервер принимает. Можно и наоборот - суть не меняется.
Проблема в том, что после первой передачи ничего не принимается, после второй - прием первой, после третьей - вторая и т.д. Получить данные без задержки можно, если сразу после передачи закрыть стрим, но это рвет соединение, а на этом этапе не хотелось бы.

Вот сервер

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
using System;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
 
namespace test_cryptoServer
{
    class Program
    {
        static void Main(string[] args)
        {
            TcpListener TCPListen = new TcpListener(IPAddress.Any, 11000);
            TCPListen.Start();
            Console.WriteLine("жду");
            TcpClient TCP = TCPListen.AcceptTcpClient();
            NetworkStream NetStream = TCP.GetStream();
            RijndaelManaged RMCrypto = new RijndaelManaged();
            byte[] Key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 };
            byte[] IV = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 };
            CryptoStream CryptStreamReader = new CryptoStream(NetStream, RMCrypto.CreateDecryptor(Key, IV), CryptoStreamMode.Read); 
            
            while(true)
            {
                byte[] msg = new byte[128];
                CryptStreamReader.Read(msg, 0, msg.Length);
                double x = BitConverter.ToDouble(msg, 0);
                Console.WriteLine("Прочел " + x);
            }
        }
    }
}
вот клиент

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
using System;
using System.Net.Sockets;
using System.Security.Cryptography;
 
namespace test_cryptoClient
{
    class Program
    {
        static void Main(string[] args)
        {
            TcpClient TCP = new TcpClient("localhost", 11000);
            NetworkStream NetStream = TCP.GetStream();
            RijndaelManaged RMCrypto = new RijndaelManaged();
            byte[] Key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 };
            byte[] IV = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 };
            CryptoStream CryptStreamWriter = new CryptoStream(NetStream, RMCrypto.CreateEncryptor(Key, IV), CryptoStreamMode.Write);
            double counter = 1;
            while (true)
            {
                Console.WriteLine("Жми!");
                Console.ReadLine();
 
                byte[] msg = new byte[128];
                byte[] tmp = BitConverter.GetBytes(counter);
                tmp.CopyTo(msg, 0);
                CryptStreamWriter.Write(msg, 0, msg.Length);
                //CryptStreamWriter.FlushFinalBlock();
                Console.WriteLine("Отправил " + counter);
                counter++;
            }
        }
    }
}
Код минимизировал для удобства восприятия. Нет выхода из цикла и т.д.. На суть вопроса не влияет))
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
19.11.2016, 20:04
Ответы с готовыми решениями:

Передача архива от клиента к серверу
Клиент скачивает файлы .txt затем их изменяет, но это всё понятно, а ещё нужно что бы клиент...

Передача двух переменных разного типа с клиента серверу
Хочу передать переменную типа float и строку типа string с асинхронного клиента на сервер, а затем...

Ошибка при сериализации от клиента серверу
Передаём данные между сервером и клиентом, при первой сериализации от клиента к серверу - всё...

Кривая отправка сообщений клиента серверу
Здравствуйте. Пишу программу, которая в системном журале отбирает все ошибки и отправляет их на...

7
Эксперт .NET
5531 / 4296 / 1216
Регистрация: 12.10.2013
Сообщений: 12,329
Записей в блоге: 2
19.11.2016, 20:33 2
mishgan2, поскольку тема в разделе WCF, то я бы посоветовал вам использовать именно это, поскольку это упростит вашу задачу в разы.
0
0 / 0 / 0
Регистрация: 06.04.2014
Сообщений: 6
19.11.2016, 22:42  [ТС] 3
insite2012, более подходящей темы не нашел. На счет wcf подумаю, спасибо за совет, но вопрос не снят, хотелось бы разобраться.
0
11 / 11 / 4
Регистрация: 03.07.2014
Сообщений: 28
20.11.2016, 14:58 4
mishgan2, для сетевого взаимодействия на сокетах управляемых вручную, это нормальное явление отправлять данные в момент когда они сами решили (например при заполнении своего внутреннего буфера). Кроме этого они ещё способны разбивать ваши данные на более мелкие части. Одним из решений является добавление в ваш пакет данных заголовка и окончания пакета.
0
0 / 0 / 0
Регистрация: 06.04.2014
Сообщений: 6
20.11.2016, 15:56  [ТС] 5
ivankon, Правильно ли я понимаю, что данные окончания пакета создаются закомментированной строчкой в примере моего клиента - CryptStreamWriter.FlushFinalBlock();? Но это же для CryptStreamWriter одноразовая операция.
Как после закрытия пакета наиболее корректно возобновить передачу? Я пробовал обновлять CryptStreamWriter через new, но не получается, CryptStreamReader на обратной стороне начинает расшифровывать неверно, хотя ключи не менялись.

Добавлено через 5 минут
Может не очень понятно написал, вот цикл клиента, который передает данные серверу:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
while (true)
            {
                Console.WriteLine("Жми!");
                Console.ReadLine();
 
                byte[] msg = new byte[128];
                byte[] tmp = BitConverter.GetBytes(counter);
                tmp.CopyTo(msg, 0);
                CryptStreamWriter = new CryptoStream(NetStream, RMCrypto.CreateEncryptor(Key, IV), CryptoStreamMode.Write);
                CryptStreamWriter.Write(msg, 0, msg.Length);
                CryptStreamWriter.FlushFinalBlock();                
                Console.WriteLine("Отправил " + counter);
                counter++;
            }
Добавлено через 10 минут
На первой итерации в строке 9 создаем CryptStreamWriter впервые. Отправляем, и затем флушим финальный блок (стрка 11). Отлично, все ушло сразу, как я и хотел. На принимающей стороне корректно расшифровалось. Но CryptStreamWriter теперь уже не рабочий. Поэтому на второй итерации мы снова его пересоздаем в строке 9. Отправляем, флушим - все ушло! Но со второго раза принимающий ридер начинает расшифровывать не корректно.
0
11 / 11 / 4
Регистрация: 03.07.2014
Сообщений: 28
20.11.2016, 17:00 6
Цитата Сообщение от mishgan2 Посмотреть сообщение
Правильно ли я понимаю, что данные окончания пакета создаются закомментированной строчкой в примере моего клиента - CryptStreamWriter.FlushFinalBlock();?
ну я правда немного не об этом говорил)
Цитата Сообщение от mishgan2 Посмотреть сообщение
Но со второго раза принимающий ридер начинает расшифровывать не корректно.
В таком случае, вам нужно попробовать пересоздать принимающий ридер.

Добавлено через 6 минут
И ещё... не отказывайтесь от совета про WCF. Дело в том что, начав его изучать только вчера, вы уже решили бы эту задачу и могли бы двигаться дальше в ваших задумках.
1
0 / 0 / 0
Регистрация: 06.04.2014
Сообщений: 6
20.11.2016, 17:39  [ТС] 7
ivankon, спасибо, пересоздавать ридер помогло. Скажите, правильно ли я понимаю, что WCF значительно более ресурсоемкая затея, нежели то, что в моих примерах. Мне просто нужно что-то максимально шустрое и легковесное, но с защитой от перехвата трафика. Задача-мониторить процессы, происходящие на сервере, отнимая как можно меньше ресурсов. WCF, как мне кажется, будет несколько тяжеловат.. Или я в корне неправ?
0
11 / 11 / 4
Регистрация: 03.07.2014
Сообщений: 28
20.11.2016, 18:03 8
По поводу производительности WCF против аналогичного кода ничего не могу сказать, т.к. написать аналогичный по функционалу код весьма не просто. Но есть несколько моментов которые возможно помогут вам с выбором:
1. библиотеки WCF (System.ServiceModel) после установки net, хранятся в GAC (Глобальный Кэш Сборок), в скомпилированном в машинный код виде (это по словам МС увеличивает скорость первого запуска на 60%)(Пусть меня поправят более опытные программисты, если я не прав)
2. с помощью WCF очень легко создать асинхронный сервер, в вашем случае я так понял будет синхронный сервер, что отнимет у ОС лишние потоки (а это весьма ценный ресурс для сервера), т.к. пул потоков приложения создаст дополнительный поток взамен ожидающего в блокировке
3. на WCF легко можно организовать передачу по нескольким каналам больших объёмов данных, для того чтобы занять всю полосу пропускания, на сокетах это сделать весьма утомительно (я делал, получилось не очень...)
1
20.11.2016, 18:03
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
20.11.2016, 18:03
Помогаю со студенческими работами здесь

Реализация клиента для подключения к серверу на WebSocket
Добрый день. Есть сервер разработанный на c++. Сервер использует подлинный сертификат и работает в...

Необработанное исключение при подключении клиента к серверу
Добрый вечер, нуждаюсь в вашей помощи. Есть у меня такой вот код: using System; using...

Socket Server/Client. Падение клиента при коннекте к серверу
В общем есть сервер: using System; using System.Collections.Generic; using System.Linq; using...

Как отловить подсоединение нового клиента к серверу на базе UDP
Здравствуйте, подскажите пожалуйста как отловить подсоединение нового клиента к серверу на базе...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru