Страницы

Поиск по вопросам

Показаны сообщения с ярлыком протоколы. Показать все сообщения
Показаны сообщения с ярлыком протоколы. Показать все сообщения

среда, 4 марта 2020 г.

Гарантированнная доставка сообщения по протоколу TCP

#c_sharp #tcp #tcp_ip #протоколы


Всем привет. Уже несколько дней ломаю голову над одной проблемой. Как то раз нашёл
пример многопользовательского клиент-серверного консольного TCP чата. И если я не ошибаюсь,
то протокол TCP не гарантирует доставку сообщения. И в случае если сообщение не будет
доставлено полностью или доставлено вообще, то надо предпринять какие-то меры. Данная
программа если я не ошибаюсь, не предпринимает никаких действий если сообщения не будет
доставлено полностью.
Вопрос: Какие меры надо предпринять чтобы обеспечить гарантированную доставку сообщения
или же, что надо делать если сообщения не будет доставлено полностью? Или может быть
программа принимает какие либо меры, если сообщение не будет доставлено полностью?
Если не трудно, то покажите,что надо добавить в программу.
Программа имеет 2 проекта Клиент и Сервер.
Код Клиента:
Класс Program:

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

namespace ChatClient
{
    class Program
    {
        static string userName; 
        private const string host = "192.168.0.107"; 
        private const int port = 20113; 
        static TcpClient client; 
        static NetworkStream stream; // Создаём объект NetworkStream, через него
можно отправлять сообщения серверу или наоборот получать

        static void Main(string[] args)
        {
            Console.Write("Введите свое имя: ");
            userName = Console.ReadLine();
            client = new TcpClient();
            try
            {
                client.Connect(host, port); //подключение клиента
                stream = client.GetStream(); // возвращает объект NetworkStream

                string message = userName;
                byte[] data = Encoding.Unicode.GetBytes(message); //Присваиваем массиву
data перекодированное сообщение
                stream.Write(data, 0, data.Length); // Передаем массив data

                // запускаем новый поток для получения данных
                Thread receiveThread = new Thread(new ThreadStart(ReceiveMessage));
                receiveThread.Start(); //старт потока
                Console.WriteLine("Добро пожаловать, {0}", userName);
                SendMessage();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                Disconnect();
            }
        }
        // отправка сообщений
        static void SendMessage()
        {
           label1: Console.WriteLine("\nВведите сообщение: ");
            while (true)
            {
                string message = Console.ReadLine();
                byte[] data = Encoding.Unicode.GetBytes(message);
                if (message != "exit")
                {
                    stream.Write(data, 0, data.Length);
                }
                else
                {
                    message = "exit";
                label2: Console.WriteLine("Вы действительно хотите выйти из чата
Y / N:");
                    switch (Console.ReadKey().Key)
                    {
                        case ConsoleKey.Y:
                            stream.Write(data, 0, data.Length);
                            Disconnect();
                            break;
                        case ConsoleKey.N:
                            goto label1;
                        default:
                            Console.WriteLine("Введите Y / N\n");
                            goto label2;
                    }    
                }
            }
        }
        // получение сообщений
        static void ReceiveMessage()
        {
            while (true)
            {
                try
                {
                    byte[] data = new byte[64]; // буфер для получаемых данных
                    StringBuilder builder = new StringBuilder();
                    int bytes = 0;
                    do
                    {
                        bytes = stream.Read(data, 0, data.Length);
                        builder.Append(Encoding.Unicode.GetString(data, 0, bytes));
                    }
                    while (stream.DataAvailable);

                    string message = builder.ToString();
                    Console.WriteLine(message);//вывод сообщения
                }
                catch
                {
                    Console.WriteLine("Подключение прервано!"); //соединение было
прервано
                    Console.ReadLine();
                    Disconnect();
                }
            }
        }
        static void Disconnect()
        {
            Console.WriteLine("disconect");
            if (stream != null)
                stream.Close();//отключение потока
            if (client != null)
                client.Close();//отключение клиента
            Environment.Exit(0); //завершение процесса  
        }
    }
}


Код Сервера:
Класс ServerObject:

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

namespace ChatServer
{
    public class ServerObject
    {
            static TcpListener tcpListener; // сервер для прослушивания
            List clients = new List(); // все подключения
            protected internal void AddConnection(ClientObject clientObject)
            {
                clients.Add(clientObject);
            }
            protected internal void RemoveConnection(string id)
            {
                // получаем по id закрытое подключение
                ClientObject client = clients.FirstOrDefault(c => c.Id == id);
                // и удаляем его из списка подключений
                if (client != null)
                    clients.Remove(client);
            }
            // прослушивание входящих подключений
            protected internal void Listen()
            {
                try
                {
                    tcpListener = new TcpListener(IPAddress.Any, 8888);
                    tcpListener.Start();
                    Console.WriteLine("Сервер запущен. Ожидание подключений...");
                    while (true)
                    {
                        TcpClient tcpClient = tcpListener.AcceptTcpClient(); //Приём
ожидающего запроса на подключение
                        ClientObject clientObject = new ClientObject(tcpClient, this);
                        Thread clientThread = new Thread(new ThreadStart(clientObject.Process));
                        clientThread.Start();
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    Disconnect();
                }
            }
            // трансляция сообщения подключенным клиентам
            protected internal void BroadcastMessage(string message, string id)
            {
                byte[] data = Encoding.Unicode.GetBytes(message);
                for (int i = 0; i < clients.Count; i++)
                {
                    if (clients[i].Id != id) // если id клиента не равно id отправляющего
                    {
                        clients[i].Stream.Write(data, 0, data.Length); //передача данных
                    }
                }
            }
            // отключение всех клиентов
            protected internal void Disconnect()
            {
                tcpListener.Stop(); //остановка сервера

                for (int i = 0; i < clients.Count; i++)
                {
                    clients[i].Close(); //отключение клиента
                }
                Environment.Exit(0); //завершение процесса
            }
        }
    }


Класс ClientObject:

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

namespace ChatServer
{
    public class ClientObject
    {
        protected internal string Id { get; private set; }
        protected internal NetworkStream Stream { get; private set; }
        string userName;
        TcpClient client;
        ServerObject server; // объект сервера

        public ClientObject(TcpClient tcpClient, ServerObject serverObject)
        {
            Id = Guid.NewGuid().ToString();
            client = tcpClient;
            server = serverObject;
            serverObject.AddConnection(this);
        }

        public void Process()
        {
            try
            {
                Stream = client.GetStream();
                // получаем имя пользователя
                string message = GetMessage();
                userName = message;
                string s = new String('*', 6);
                message = userName + " вошел в чат";
                // посылаем сообщение о входе в чат всем подключенным пользователям
                server.BroadcastMessage(message, this.Id);
                Console.WriteLine(message);
                // в бесконечном цикле получаем сообщения от клиента
                while (true) 
                {
                    try
                    {
                        message = GetMessage();
                    if (message == "exit")
                        {
                            message = String.Format($"{s}{userName}: покинул чат{s}");
                            Console.Write(message);
                            server.BroadcastMessage(message, this.Id);
                            break;

                        }
                    else
                        {
                            message = String.Format($"{userName}: {message}");
                            Console.WriteLine(message);
                            server.BroadcastMessage(message, this.Id);
                        }
                    }
                    catch
                    {
                        message = String.Format($"{s}{userName}: покинул чат{s}");
                        Console.Write(message);
                        server.BroadcastMessage(message, this.Id);
                        break;
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            finally
            {
                // в случае выхода из цикла закрываем ресурсы
                server.RemoveConnection(this.Id);
                Close();
            }
        }

        // чтение входящего сообщения и преобразование в строку
        private string GetMessage()
        {
            byte[] data = new byte[64]; // буфер для получаемых данных
            StringBuilder builder = new StringBuilder();
            int bytes = 0;
            do
            {
                bytes = Stream.Read(data, 0, data.Length);
                builder.Append(Encoding.Unicode.GetString(data, 0, bytes));
            }
            while (Stream.DataAvailable);

            return builder.ToString();
        }

        // закрытие подключения
        protected internal void Close()
        {
            if (Stream != null)
                Stream.Close();
            if (client != null)
                client.Close();
        }
    }
}


Класс Program:

using System;
using System.Threading;

namespace ChatServer
{
    class Program
    {
            static ServerObject server; // сервер
            static Thread listenThread; // потока для прослушивания
            static void Main(string[] args)
            {
                try
                {
                    server = new ServerObject();
                    listenThread = new Thread(new ThreadStart(server.Listen));
                    listenThread.Start(); //старт потока
                }
                catch (Exception ex)
                {
                    server.Disconnect();
                    Console.WriteLine(ex.Message);
                }
            }
        }
    }


Пытался сделать так как посоветовал PashaPash, но всё без результатно.
Как мне посоветовал PashaPash я добавил признак окончания сообщения '/'

do
{
}
while (bytes==(byte)'/');



Если я правильно понял данные должны считываться как-то с помощью  StreamReader
Но как накапливать данные в MemoryStream не очень понятно?
    


Ответы

Ответ 1



TCP гарантирует доставку. Проблема в вашем коде в том, что он предполагает, что то, что передано в один вызов Write, будет вычитано одним вызовом Read на другой стороне. А это не так. Write не "отправляет пакет". Он просто пишет данные в сокет. А Read не "читает пакет". Он вычитывает из буфера сокета то, что успело дойти. Если вы сделали два вызова Write, подождали, и сделали один Read - вычитаются данные обоих вызовов. Если вы сделали вызов Write, и данные не успели дойти - Read вычитает только начало (начало строки, в вашем случае). Обработка в цикле с builder.Append - ненадежна, т.к. ваш код читает из локального буфера, очень быстро (быстрее, чем данные идут по сети!), и достигает состояния !Stream.DataAvailable где-то на середине сообщения. Кроме того, он считает, что каждый результат Read может быть преобразован в Unicode строку. И никак не учитывает, что может получить фрагмент с половиной символа в конце или начале. Надежные способы, на выбор: Передавать перед каждым сообщением его длину. Не читать напрямую из Stream - обернуть его в BinaryReader, и читать длину (reader.ReadInt32()), потом - ровно столько байт, сколько нужно (reader.GetBytes(messageLength) будет ждать, пока не придет нужное количество байт). Или использовать binaryWriter.Write(message) / binaryReader.ReadString(), который автоматически делают то же самое за вам. Ввести признак окончания сообщения, например символ переноса строки. Читать до тех пор, пока в прочитанном фрагмент нет соответствующего байта (а не по Stream.DataAvailable). И при этом накапливать вычитанное в MemoryStream, в виде байт чтобы избежать проблем с половиной юникодового символа. В конце преобразовывать в строчку все сообщение целиком. Пример на коде из вопроса (с минимальными изменениями): Клиент - просто заменяете работу со stream на работу с reader / writer: using System; using System.IO; using System.Net.Sockets; using System.Text; using System.Threading; namespace ChatClient { class Program { static string userName; private const string host = "127.0.0.1"; private const int port = 8888; static TcpClient client; static BinaryReader reader; static BinaryWriter writer; static void Main(string[] args) { Console.Write("Введите свое имя: "); userName = Console.ReadLine(); client = new TcpClient(); try { client.Connect(host, port); //подключение клиента var stream = client.GetStream(); // возвращает объект NetworkStream reader = new BinaryReader(stream, Encoding.Unicode, true); writer = new BinaryWriter(stream, Encoding.Unicode, true); writer.Write(userName); // запускаем новый поток для получения данных Thread receiveThread = new Thread(new ThreadStart(ReceiveMessage)); receiveThread.Start(); //старт потока Console.WriteLine("Добро пожаловать, {0}", userName); SendMessage(); } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { Disconnect(); } } // отправка сообщений static void SendMessage() { label1: Console.WriteLine("\nВведите сообщение: "); while (true) { string message = Console.ReadLine(); if (message != "exit") { writer.Write(message); } else { message = "exit"; label2: Console.WriteLine("Вы действительно хотите выйти из чата Y / N:"); switch (Console.ReadKey().Key) { case ConsoleKey.Y: writer.Write(message); Disconnect(); break; case ConsoleKey.N: goto label1; default: Console.WriteLine("Введите Y / N\n"); goto label2; } } } } // получение сообщений static void ReceiveMessage() { while (true) { try { string message = reader.ReadString(); Console.WriteLine(message);//вывод сообщения } catch { Console.WriteLine("Подключение прервано!"); //соединение было прервано Console.ReadLine(); Disconnect(); } } } static void Disconnect() { Console.WriteLine("disconect"); if (client != null) client.Close();//отключение клиента Environment.Exit(0); //завершение процесса } } } Сервер - то же самое, с указанием той же кодировки: using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Net; using System.Text; using System.Threading; namespace ChatServer { public class ServerObject { static TcpListener tcpListener; // сервер для прослушивания List clients = new List(); // все подключения protected internal void AddConnection(ClientObject clientObject) { clients.Add(clientObject); } protected internal void RemoveConnection(string id) { // получаем по id закрытое подключение ClientObject client = clients.FirstOrDefault(c => c.Id == id); // и удаляем его из списка подключений if (client != null) clients.Remove(client); } // прослушивание входящих подключений protected internal void Listen() { try { tcpListener = new TcpListener(IPAddress.Any, 8888); tcpListener.Start(); Console.WriteLine("Сервер запущен. Ожидание подключений..."); while (true) { TcpClient tcpClient = tcpListener.AcceptTcpClient(); //Приём ожидающего запроса на подключение ClientObject clientObject = new ClientObject(tcpClient, this); Thread clientThread = new Thread(new ThreadStart(clientObject.Process)); clientThread.Start(); } } catch (Exception ex) { Console.WriteLine(ex.Message); Disconnect(); } } // трансляция сообщения подключенным клиентам protected internal void BroadcastMessage(string message, string id) { for (int i = 0; i < clients.Count; i++) { if (clients[i].Id != id) // если id клиента не равно id отправляющего { clients[i].SendMessage(message); //передача данных } } } // отключение всех клиентов protected internal void Disconnect() { tcpListener.Stop(); //остановка сервера for (int i = 0; i < clients.Count; i++) { clients[i].Close(); //отключение клиента } Environment.Exit(0); //завершение процесса } } } using System; using System.IO; using System.Net.Sockets; using System.Text; namespace ChatServer { public class ClientObject { protected internal string Id { get; private set; } string userName; TcpClient client; ServerObject server; // объект сервера BinaryWriter writer; public ClientObject(TcpClient tcpClient, ServerObject serverObject) { Id = Guid.NewGuid().ToString(); client = tcpClient; server = serverObject; serverObject.AddConnection(this); } public void Process() { try { var stream = client.GetStream(); this.writer = new BinaryWriter(stream, Encoding.Unicode, false); var reader = new BinaryReader(stream, Encoding.Unicode, false); // получаем имя пользователя string message = reader.ReadString(); userName = message; string s = new String('*', 6); message = userName + " вошел в чат"; // посылаем сообщение о входе в чат всем подключенным пользователям server.BroadcastMessage(message, this.Id); Console.WriteLine(message); // в бесконечном цикле получаем сообщения от клиента while (true) { try { message = reader.ReadString(); if (message == "exit") { message = String.Format($"{s}{userName}: покинул чат{s}"); Console.Write(message); server.BroadcastMessage(message, this.Id); break; } else { message = String.Format($"{userName}: {message}"); Console.WriteLine(message); server.BroadcastMessage(message, this.Id); } } catch { message = String.Format($"{s}{userName}: покинул чат{s}"); Console.Write(message); server.BroadcastMessage(message, this.Id); break; } } } catch (Exception e) { Console.WriteLine(e.Message); } finally { // в случае выхода из цикла закрываем ресурсы server.RemoveConnection(this.Id); Close(); } } internal void SendMessage(string message) { this.writer.Write(message); } public void Close() { if (client != null) client.Dispose(); } } }

пятница, 28 февраля 2020 г.

Как сгенерировать ASCII для сетевых протоколов в консоли?

#python #сеть #tcp #протоколы


Есть какая-нибудь консольная утилита, которая позволяет просматривать ASCII-диаграммы
для сетевых протоколов непосредственно в консоли?
    


Ответы

Ответ 1



Да, есть консольная утилита protocol, написанная на python, которая позволяет взглянуть на стандартные заголовки сетевых протоколов прямо в консоли, без необходимости искать информацию в интернетах. Для установки инструмента выполните: git clone https://github.com/luismartingarcia/protocol.git сd protocol sudo ./setup.py install Собственно, всё! Проверим как работает, выполним: protocol ethernet Получаем ASCII-диаграмму для ethernet: Более подробная информация здесь.

четверг, 13 февраля 2020 г.

Запуск приложения с помощью собственного протокола

#c_sharp #windows #net #протоколы


На сетевом диске лежит приложение abc.exe.
Как написать протокол, чтобы такая команда abc:\\param запускала это приложение с
параметром param?
Как пишется протокол?
Все ли пользователи, имеющие доступ к шаре смогут использовать такой протокол или
требуется на каждой машине требуется выполнить еще что-то?
    


Ответы

Ответ 1



Протокол прописывается в реестре Windows. Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\yourprotocolname] @="URL:Direct Connect Protocol" "URL Protocol"="" [HKEY_CLASSES_ROOT\yourprotocolname\Shell\Open\Command] @="cmd /c echo %1 & pause" Обращаю внимание, что в браузере можно создавать ссылки на такой протокол. И таким ссылкам можно настроить автоматическое выполнение без запроса. Поэтому очень важно отнестись к обработке передаваемых параметров внимательно. Например, определённый выше протокол с именем yourprotocolname представляет собой огромную дыру в безопасности, поскольку можно сделать что-то типа yourprotocolname:text & format d: PS: Знаю, что в linux'е тоже возможно создавать кастомные протоколы, но не имею ни малейшего представления, как это делать.

вторник, 28 января 2020 г.

Является ли курьер с документами протоколом передачи данных?

#теория #протоколы


Моего коллегу Константина начальство послало в соседний корпус с документами, которые
он должен отдать. 

Вопрос: с точки зрения теории информации и других компьютерных наук можем ли мы считать
Константина протоколом передачи данных, а окружающий его холод улицы (в процессе движения)
- средой распространения информации?

PS. Вопрос не ради хохмы, пишу методичку для чайников по информатике. 
    


Ответы

Ответ 1



Конечно же конкретный курьер Константин не является протоколом. И даже абстрактный курьер протоколом не является. Протокол - это не физическая сущность, это описание процесса, обобщенный алгоритм. Ниже я рассмотрел подробнее как могли бы выглядеть протоколы разных уровней в этом стеке. Физический уровень. Как происходит передача документов курьером? Директор вызывает курьера Директор передаёт документы курьеру Курьер идёт в соседний корпус к получателю документов Курьер передаёт документы получателю Получатель говорит курьеру "спасибо" (или "ну наконец-то") и забирает документы Попытаемся обобщить этот алгоритм, избавившись от слишком конкретных шагов. Интересно ли получателю то, как директор передавал документы курьеру? Нет, ему интересны только сами документы. Интересно ли директору, как получатель забирал документы? Нет, ему важен только чтобы получатель их получил. Остаётся от алгоритма следующее: "курьер берёт документы и идёт с ними к получателю, после чего отдаёт их получателю". Это и есть протокол физического уровня. Что же такое в таком случае курьер в этой аналогии? А курьер тут - среда. То, что переносит информацию. Теперь канальный уровень. Канальный уровень управляет доступом к среде. К протоколу канального уровня относятся алгоритмы вызова курьера, в который надо предусмотреть ситуации "что делать если курьер занят" (директор может подождать или назначить курьером кого-то ещё - во втором случае средой передачи станет множество курьеров), "что делать если курьера пытается отправить не директор, а кто-то ещё" или "как курьер узнает получателя" (да-да, в этом стеке протоколов будущего предусмотрена авторизация на канальном уровне!) Сетевой и транспортный уровни. В вашем примере эти уровни не предусмотрен, поскольку курьер принципиально один. Однако, можно придумать другой пример, в котором один курьер будет передавать документ другому или вообще пойдёт на почту. Это и будет протоколом сетевого уровня. Протокол же транспортного уровня будет отвечать за подтверждение доставки (или не будет, см. UDP) Прикладной уровень. На этом уровне описывается формат передаваемого документа.

Ответ 2



Нет, не можем. Протокол, это скорее соглашение о том, что информация передаётся таким-то способом. Соглашение о том, что документы пересылаются курьерами - это протокол. Ваш Константин его конкретная реализация (одна из возможных). Улица - среда. Холод - один из параметров среды. Как-то так...

Ответ 3



Если рассматривать модель OSI, то Физический уровень (то, где перемещается курьер) город, область, Вселенная Канальный (откуда и куда) Улица, здание или кабинет Сетевой (способ перемещения пакета данных) Курьер Транспортный (надёжность и скорость доставки) Его портфель Сеансовый (возьми это и отдай туда, мне доложи) Секретарша Представительский (секретный документ в конверт и в отправку) Директор Прикладной (я сделаю документ, а дальше отправляйте куда хотите) Главбух

Ответ 4



Протокол (любого уровня) - это способ передачи данных, в том числе способ с применением Константина. Если Константин придерживается ряда строгих правил и его участие в процессе обмена согласовано как передающей, так и принимающей стороной - его можно считать протоколом. В разрезе модели OSI курьер Константин, конечно же, выполняет свои функции на уровне транспортного протокола, а именно - обеспечивает надёжную передачу данных от отправителя к получателю. Рассмотрим всю цепочку обмена: Представим, что некая секретарша (которая, конечно же, работает на уровне представления) заботливо запечатывает данные, полученные от прикладного уровня в виде руководства (отчёты, денежные средства, договоры и пр.) в конверт, а затем передаёт их в качестве поручения Константину, с которым она предварительно познакомилась и возможно, даже планирует поддерживать длительные дружеские отношения до тех пор, пока он работает в Компании (так сказать, на сеансовом уровне). Костик совершенно не в курсе о назначении передаваемых им сообщений, но его это и не интересует. Он заворачивает их в своё пальто, чтобы пакет с доносами и кляузами на коллег не промок и не принял непристойный вид в результате попадания под проливной питерский дождь). И извлечёт Константин этот пакет не раньше, чем войдёт в сухое и теплое помещение пункта назначения, уж будьте уверены. Нет, его конечно могут принудительно заставить раздеться и даже пройти досмотр на входе в метро, но вот внутрь конверта ни у кого по пути заглянуть не получится - ведь документы надежно запечатаны, и распечатать их можно, лишь разорвав конверт. В процессе совершения доставки он пользуется подсказками о координатах конечного пункта, которые содержатся на сетевом в виде набора адресов, каждый из которых присвоен отдельному зданию или кабинету. Если Константин перед отправлением не выяснил точное месторасположение пункта назначения, ему придётся буквально уткнуться ("завернуться") в карту района и следуя по пути, постоянно сверяться с её содержимым. Константину свойственны и некоторые типичные проблемы транспортного уровня: Его надежность находится под вопросом: для подтверждения факта успешной доставки им данных в конечный пункт может потребоваться подтверждение. Но зачастую из-за высоких накладных расходов на такие подтверждения в компаниях кладут болт, ведь доля потерянных Константинов в течение рабочего дня обычно незначительна. Гарантирует ли Константин правильную последовательность получения адресатом отправленных данных? Разумеется, да. Как правило, следующее поручение Константину будет выдано лишь после возвращения его в исходный пункт. В случае внезапной пропажи Константина налаженный механизм обмена документами в Компании прервётся, но не надолго. Обворожительной секретарше придётся вновь составить поручение, но уже передать его другому курьеру. И процесс обмена будет запущен вновь. Замечу ещё, что весь городской транспорт, тротуары, коридоры, а также прочая канальная инфраструктура доступного для доставки сегмента (города, района или кампуса крупной компании), по которой возможно перемещение Константина, используются им в процессе доставки данных. В их числе, кстати могут оказаться и мосты ;) которые в модели OSI работают как раз-таки на канальном уровне. Что же является низшим, физическим протоколом в этом случае? Ни воздух, ни город, ни сама по себе Вселенная сигналы не распространяют, то есть средой они конечно являются, а вот протоколом физического уровня - нет. А протоколом я бы назвал физическое перемещение от отправителя к адресату, ведь именно этот процесс лежит в основе передачи информации. Итак, резюмирую - передача сообщений с помощью Константина - это явный пример использования курьер-подобного протокола обмена.

пятница, 24 января 2020 г.

Какой протокол передачи данных, использует stackoverflow.com

#http #https #протоколы #stackoverflow_api


Какой протокол передачи данных, использует stackoverflow.com?
Интересует протокол прикладного уровня. 

Интересно, когда находишься на странице, то её не обязательно обновлять для того
что бы увидеть новые ответ или комментарий. Получается или веб-приложение stackoverflow.com
запрашивает через каждые n секунд, работая через HTTP, или использует протокол двусторонней
связи. 
    


Ответы

Ответ 1



Из первых рук (перевод) Мы используем Websockets для осуществления принудительных обновлений в режиме реального времени, таких как показ уведомлений в верхнем горизонтальном меню, подсчет голосов, формирование статистики новой навигации, показ новых ответов и комментариев, и еще для нескольких задач.

Программа для видеозахвата

#c_sharp #камера #протоколы


Задача такая. Необходимо создать приложение по наблюдению за кассирами.
Существует база данных с операциями по кассирам, пробитие чека,
аннулирование  и т.д.


Была задумка по определенной выборке находить необходимые события по
кассе,
далее по событию находить нужный фрагмент видео в архиве, т.е.
ориентироваться по времени чека(события)
и вставать на фрагмент этого места в видео файле
так же необходима возможность онлайн контроля процесса продажи.


Вопрос с чего начать, немного поискав понял что даже IP камеры несколько
протоколов,
а в наличии есть еще и аналоговые камеры...
Возможно есть смысл онлайн контроль осуществлять с помощью какой то
"бесплатной" готовой программы
настроить чтобы программа могла писать в какой нибудь определенный
распространенный формат AVI например.

А приложение уже писать самому и разбирать видео файлы, которые будут
создаваться бесплатной программой.

желательно писать на C#, есть опыт.

с помощью какой библиотеки можно подружить камеры протокола rtsp с приложением C#(показывать
видео онлайн, и писать его в архив)?
    


Ответы

Ответ 1



с помощью какой библиотеки можно подружить камеры протокола rtsp с приложением C#(показывать видео онлайн, и писать его в архив)? Посмотрите net7mma.codeplex.com Проект активно развивается, и в сети довольно много упоминаний, включая EnSO, возможно эта библиотека перекроет ваши задачи.

воскресенье, 12 января 2020 г.

Как пользоваться MAP-протоколом. Отправка сообщения на SMS-центр

#java #sms #протоколы


Есть MAP-сообщение (Mobile Application Part), которое необходимо доставить в SMS-центр.
Как возможно реализовать эту отправку? Может быть через socket? Или с помощью USB-модема
с сим-картой? Или как вообще? Адрес SMS-центра очень похож на номер телефона.

Желательно реализовать всё на Java. С C++'ом не разбираюсь.



Сообщение send routing info for sm, насколько знаю, можно отправлять только с помощью
протокола MAP, поэтому именно он мне и нужен. Подскажите, если есть другие протоколы,
которые могут отправлять такое же или похожее сообщение.
    


Ответы

Ответ 1



Никак. MAP это сигнальный протокол из стека SS7, обеспечивающий коммуникацию между базовыми станциями и коммутационным центром в пределах одного оператора связи. За его пределами он никак не используется, и в нормальных условях нет возможности как-то повлиять "человеку со стороны" на передающиеся с его помощью сигналы. Хотя да, есть протокол SCTP являющийся транспортным протоколом IP(наравне с TCP и UDP), позволяющий "заворачивать" внутрь себя SS7, и когда-то давно у некоторых сотовых операторов(в основном на западе) точки подключения к SCTP были выведены напрямую в сеть интернет и были доступны каждому кто о них знал - что повело к ряду "взломов и нештатного использования". Наличие таких операторов сейчас - очень сомнительно. На оконечных устройствах SS7(и в том числе MAP) не используется, так что "с помощью GSM-модема" в сигнальную линию SS7 вы ничего не отправите. Служебное сообщение "SEND-ROUTING-INFO-FOR-SM" позволяет оператору запросить список идентификаторов базовых станций к которым в данный момент подключен его абонент, а так же дополнительную информацию, позволяющую косвенно определить географическую удаленность устройства от этих базовых станций. Ответ от абонентского устройства поступает в СМС-центр. Изначально это сообщение разрабатывалось для совсем иных целей, но да, сейчас оно приемущественно используется сотовыми операторами для отслеживания текущего положения абонента по запросу спецслужб. Если вы не являетесь компанией-оператором абонента или контролирующей его спецслужбой, то: Отправить это служебное сообщение вам не удастся - необходимо иметь доступ к комуникационному ядру оператора сотовой связи абонента и/или его базовым станциям, для его отправки с помощью MAP Принять ответ на него вы тоже не сможете - необходима возможность чтения служебных сообщений приходящих в SMS-центр оператора Ну и интерпретировать ответ от устройства абонента у вас тоже не получится - нужно иметь доступ к базе данных HLR оператора, что бы иметь возможность преобразовать полученые идентификаторы его базовых станций в географические координаты. Узнать достаточно точное положение устройства абонента можно только сопоставив географические кординаты базовых станций и удаленность устройства от них.

Ответ 2



В ряде стран получить лицензию моб. оператора и подключится к SS7 не составляет проблем. Т.е. часть из них сливает возможность соединения(скорей всего не официально), ну поискав в англоязычном интернете найти то что вам надо(опасайтесь мошенников, просите тест, платите мелкими сумами). Насчет законности, я не уверен но наверняка существуют страны где это вполне законно(все на ваш страх и риск).

воскресенье, 1 декабря 2019 г.

Протокол для многопользовательской игры

#cpp #websocket #tcp #udp #протоколы


Добрый день,

проект - многопользовательская игра, расчитаная на множество игроков (до 100), наподобие
agar.io и тд. Сервер на C++, интерфейс - JavaScript (всё происходит внутри браузера).
Стоит вопрос, как реализовывать передачу данных. 

Идеи :


TCP - WebSocket
UDP - разрабатывающийся "протокол" netcode.io (но ввиду того, что портируемость только
на Windows, идея отброшена)


Уважаемые пользователи, может вы можете подсказать, как лучше сие реализовывать.
А если уж WebSocket предлагаете, то какую библиотеку для него использовать в C++?
    


Ответы

Ответ 1



Ну с протоколом вы уже определились в своем же вопросе. Как лучше "сие" реализовать: Для вас идеальный вариант (если это js клиент и c++ server и до 100 юзеров): Библиотека: socket.io Пример сервера на c++: c++ socket.io server При правильном подходе и железе такой сервер выдержит не одну тысячу пользователей онлайн.

Ответ 2



Привет, Вам подойдет Poco. Там есть реализация WebSocket и JSON - очень удобно. Для обеспечения хорошей скорости, желательно разбивать информацию на маленькие сообщения. Например, организовать связь между взаимосвязанными объектами на сервере и на странице, а WebSocket соединение использовать как роутер между ними.

суббота, 6 июля 2019 г.

Виртуальный метод при композиции

Объект класса с двумя методами getOuter и getInner оборачивается другим классом, имеющим такой же интерфейс, но используется не наследование а композиция, т. е. объект вкладывается внутрь другого и они должны иметь независимые поля.
Известно, что из метода getOuter ровно один раз вызывается метод getInner. Надо сделать так, чтобы вызывался getInner не оборачиваемого объекта, а оборачивающего. В качестве прокси используется класс Wrapper, от которого наследуются обрачивающие классы. Что надо в него дописать, чтобы работало соответствующим образом?
Желаемый вывод после дописывания врэппера:
outer c b a (<[Bb][Aa]>)
class A { constructor() { this.x = 'A'; this.a = 'a'; } getOuter() { console.log('outer'); return `(${this.getInner()})`; } getInner() { console.log('a'); return this.x + this.a; } } var a = new A class Wrapper { constructor(original) { this.original = original } getOuter() { return this.original.getOuter(); } getInner() { return this.original.getInner(); } } class B extends Wrapper { constructor(original) { super(original); this.x = 'B'; this.b = 'b'; } getInner() { console.log('b'); return `[${this.x}${this.b}][${super.getInner()}]`; } } var b = new B(a); class C extends Wrapper { constructor(original) { super(original); this.x = 'C'; this.c = 'c'; } getInner() { console.log('c'); return `<${this.x}${this.c}><${super.getInner()}>`; } } var c = new C(b); console.log(c.getOuter());


Ответ

Ура, кажется получилось!
Надо в getOuter в оборачиваемый инстанс сохранить забинженный метод getInner текущего класса, в когда тот вызовет super.getInner, то эту ссылку затереть и продолжить вызывать по цепочке:
class A { constructor() { this.x = 'A'; this.a = 'a'; } getOuter() { console.log('outer'); return `(${this.getInner()})`; } getInner() { console.log('a'); return this.x + this.a; } } var a = new A class Wrapper { constructor(original) { this.original = original } getOuter() { this.original.getInner = this.getInner.bind(this); return this.original.getOuter(); } getInner() { delete this.original.getInner; return this.original.getInner(); } } class B extends Wrapper { constructor(original) { super(original); this.x = 'B'; this.b = 'b'; } getInner() { console.log('b'); return `[${this.x}${this.b}][${super.getInner()}]`; } } var b = new B(a); class C extends Wrapper { constructor(original) { super(original); this.x = 'C'; this.c = 'c'; } getInner() { console.log('c'); return `<${this.x}${this.c}><${super.getInner()}>`; } } var c = new C(b); console.log(c.getOuter());

понедельник, 20 мая 2019 г.

Гарантированнная доставка сообщения по протоколу TCP

Всем привет. Уже несколько дней ломаю голову над одной проблемой. Как то раз нашёл пример многопользовательского клиент-серверного консольного TCP чата. И если я не ошибаюсь, то протокол TCP не гарантирует доставку сообщения. И в случае если сообщение не будет доставлено полностью или доставлено вообще, то надо предпринять какие-то меры. Данная программа если я не ошибаюсь, не предпринимает никаких действий если сообщения не будет доставлено полностью. Вопрос: Какие меры надо предпринять чтобы обеспечить гарантированную доставку сообщения или же, что надо делать если сообщения не будет доставлено полностью? Или может быть программа принимает какие либо меры, если сообщение не будет доставлено полностью? Если не трудно, то покажите,что надо добавить в программу. Программа имеет 2 проекта Клиент и Сервер. Код Клиента: Класс Program:
using System; using System.Net.Sockets; using System.Text; using System.Threading;
namespace ChatClient { class Program { static string userName; private const string host = "192.168.0.107"; private const int port = 20113; static TcpClient client; static NetworkStream stream; // Создаём объект NetworkStream, через него можно отправлять сообщения серверу или наоборот получать
static void Main(string[] args) { Console.Write("Введите свое имя: "); userName = Console.ReadLine(); client = new TcpClient(); try { client.Connect(host, port); //подключение клиента stream = client.GetStream(); // возвращает объект NetworkStream
string message = userName; byte[] data = Encoding.Unicode.GetBytes(message); //Присваиваем массиву data перекодированное сообщение stream.Write(data, 0, data.Length); // Передаем массив data
// запускаем новый поток для получения данных Thread receiveThread = new Thread(new ThreadStart(ReceiveMessage)); receiveThread.Start(); //старт потока Console.WriteLine("Добро пожаловать, {0}", userName); SendMessage(); } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { Disconnect(); } } // отправка сообщений static void SendMessage() { label1: Console.WriteLine("
Введите сообщение: "); while (true) { string message = Console.ReadLine(); byte[] data = Encoding.Unicode.GetBytes(message); if (message != "exit") { stream.Write(data, 0, data.Length); } else { message = "exit"; label2: Console.WriteLine("Вы действительно хотите выйти из чата Y / N:"); switch (Console.ReadKey().Key) { case ConsoleKey.Y: stream.Write(data, 0, data.Length); Disconnect(); break; case ConsoleKey.N: goto label1; default: Console.WriteLine("Введите Y / N
"); goto label2; } } } } // получение сообщений static void ReceiveMessage() { while (true) { try { byte[] data = new byte[64]; // буфер для получаемых данных StringBuilder builder = new StringBuilder(); int bytes = 0; do { bytes = stream.Read(data, 0, data.Length); builder.Append(Encoding.Unicode.GetString(data, 0, bytes)); } while (stream.DataAvailable);
string message = builder.ToString(); Console.WriteLine(message);//вывод сообщения } catch { Console.WriteLine("Подключение прервано!"); //соединение было прервано Console.ReadLine(); Disconnect(); } } } static void Disconnect() { Console.WriteLine("disconect"); if (stream != null) stream.Close();//отключение потока if (client != null) client.Close();//отключение клиента Environment.Exit(0); //завершение процесса } } }
Код Сервера: Класс ServerObject:
using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Net; using System.Text; using System.Threading;
namespace ChatServer { public class ServerObject { static TcpListener tcpListener; // сервер для прослушивания List clients = new List(); // все подключения protected internal void AddConnection(ClientObject clientObject) { clients.Add(clientObject); } protected internal void RemoveConnection(string id) { // получаем по id закрытое подключение ClientObject client = clients.FirstOrDefault(c => c.Id == id); // и удаляем его из списка подключений if (client != null) clients.Remove(client); } // прослушивание входящих подключений protected internal void Listen() { try { tcpListener = new TcpListener(IPAddress.Any, 8888); tcpListener.Start(); Console.WriteLine("Сервер запущен. Ожидание подключений..."); while (true) { TcpClient tcpClient = tcpListener.AcceptTcpClient(); //Приём ожидающего запроса на подключение ClientObject clientObject = new ClientObject(tcpClient, this); Thread clientThread = new Thread(new ThreadStart(clientObject.Process)); clientThread.Start(); } } catch (Exception ex) { Console.WriteLine(ex.Message); Disconnect(); } } // трансляция сообщения подключенным клиентам protected internal void BroadcastMessage(string message, string id) { byte[] data = Encoding.Unicode.GetBytes(message); for (int i = 0; i < clients.Count; i++) { if (clients[i].Id != id) // если id клиента не равно id отправляющего { clients[i].Stream.Write(data, 0, data.Length); //передача данных } } } // отключение всех клиентов protected internal void Disconnect() { tcpListener.Stop(); //остановка сервера
for (int i = 0; i < clients.Count; i++) { clients[i].Close(); //отключение клиента } Environment.Exit(0); //завершение процесса } } }
Класс ClientObject:
using System; using System.Net.Sockets; using System.Text;
namespace ChatServer { public class ClientObject { protected internal string Id { get; private set; } protected internal NetworkStream Stream { get; private set; } string userName; TcpClient client; ServerObject server; // объект сервера
public ClientObject(TcpClient tcpClient, ServerObject serverObject) { Id = Guid.NewGuid().ToString(); client = tcpClient; server = serverObject; serverObject.AddConnection(this); }
public void Process() { try { Stream = client.GetStream(); // получаем имя пользователя string message = GetMessage(); userName = message; string s = new String('*', 6); message = userName + " вошел в чат"; // посылаем сообщение о входе в чат всем подключенным пользователям server.BroadcastMessage(message, this.Id); Console.WriteLine(message); // в бесконечном цикле получаем сообщения от клиента while (true) { try { message = GetMessage(); if (message == "exit") { message = String.Format($"{s}{userName}: покинул чат{s}"); Console.Write(message); server.BroadcastMessage(message, this.Id); break;
} else { message = String.Format($"{userName}: {message}"); Console.WriteLine(message); server.BroadcastMessage(message, this.Id); } } catch { message = String.Format($"{s}{userName}: покинул чат{s}"); Console.Write(message); server.BroadcastMessage(message, this.Id); break; } } } catch (Exception e) { Console.WriteLine(e.Message); } finally { // в случае выхода из цикла закрываем ресурсы server.RemoveConnection(this.Id); Close(); } }
// чтение входящего сообщения и преобразование в строку private string GetMessage() { byte[] data = new byte[64]; // буфер для получаемых данных StringBuilder builder = new StringBuilder(); int bytes = 0; do { bytes = Stream.Read(data, 0, data.Length); builder.Append(Encoding.Unicode.GetString(data, 0, bytes)); } while (Stream.DataAvailable);
return builder.ToString(); }
// закрытие подключения protected internal void Close() { if (Stream != null) Stream.Close(); if (client != null) client.Close(); } } }
Класс Program:
using System; using System.Threading;
namespace ChatServer { class Program { static ServerObject server; // сервер static Thread listenThread; // потока для прослушивания static void Main(string[] args) { try { server = new ServerObject(); listenThread = new Thread(new ThreadStart(server.Listen)); listenThread.Start(); //старт потока } catch (Exception ex) { server.Disconnect(); Console.WriteLine(ex.Message); } } } }
Пытался сделать так как посоветовал PashaPash, но всё без результатно. Как мне посоветовал PashaPash я добавил признак окончания сообщения '/'
do { } while (bytes==(byte)'/');
Если я правильно понял данные должны считываться как-то с помощью StreamReader Но как накапливать данные в MemoryStream не очень понятно?


Ответ

TCP гарантирует доставку.
Проблема в вашем коде в том, что он предполагает, что то, что передано в один вызов Write, будет вычитано одним вызовом Read на другой стороне. А это не так.
Write не "отправляет пакет". Он просто пишет данные в сокет.
А Read не "читает пакет". Он вычитывает из буфера сокета то, что успело дойти.
Если вы сделали два вызова Write, подождали, и сделали один Read - вычитаются данные обоих вызовов.
Если вы сделали вызов Write, и данные не успели дойти - Read вычитает только начало (начало строки, в вашем случае).
Обработка в цикле с builder.Append - ненадежна, т.к. ваш код читает из локального буфера, очень быстро (быстрее, чем данные идут по сети!), и достигает состояния !Stream.DataAvailable где-то на середине сообщения. Кроме того, он считает, что каждый результат Read может быть преобразован в Unicode строку. И никак не учитывает, что может получить фрагмент с половиной символа в конце или начале.
Надежные способы, на выбор:
Передавать перед каждым сообщением его длину. Не читать напрямую из Stream - обернуть его в BinaryReader, и читать длину (reader.ReadInt32()), потом - ровно столько байт, сколько нужно (reader.GetBytes(messageLength) будет ждать, пока не придет нужное количество байт). Или использовать binaryWriter.Write(message) / binaryReader.ReadString(), который автоматически делают то же самое за вам. Ввести признак окончания сообщения, например символ переноса строки. Читать до тех пор, пока в прочитанном фрагмент нет соответствующего байта (а не по Stream.DataAvailable). И при этом накапливать вычитанное в MemoryStream, в виде байт чтобы избежать проблем с половиной юникодового символа. В конце преобразовывать в строчку все сообщение целиком.
Пример на коде из вопроса (с минимальными изменениями):
Клиент - просто заменяете работу со stream на работу с reader / writer:
using System; using System.IO; using System.Net.Sockets; using System.Text; using System.Threading;
namespace ChatClient { class Program { static string userName; private const string host = "127.0.0.1"; private const int port = 8888; static TcpClient client; static BinaryReader reader; static BinaryWriter writer;
static void Main(string[] args) { Console.Write("Введите свое имя: "); userName = Console.ReadLine(); client = new TcpClient(); try { client.Connect(host, port); //подключение клиента var stream = client.GetStream(); // возвращает объект NetworkStream reader = new BinaryReader(stream, Encoding.Unicode, true); writer = new BinaryWriter(stream, Encoding.Unicode, true);
writer.Write(userName);
// запускаем новый поток для получения данных Thread receiveThread = new Thread(new ThreadStart(ReceiveMessage)); receiveThread.Start(); //старт потока Console.WriteLine("Добро пожаловать, {0}", userName); SendMessage(); } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { Disconnect(); } }
// отправка сообщений static void SendMessage() { label1: Console.WriteLine("
Введите сообщение: "); while (true) { string message = Console.ReadLine(); if (message != "exit") { writer.Write(message); } else { message = "exit"; label2: Console.WriteLine("Вы действительно хотите выйти из чата Y / N:"); switch (Console.ReadKey().Key) { case ConsoleKey.Y: writer.Write(message); Disconnect(); break; case ConsoleKey.N: goto label1; default: Console.WriteLine("Введите Y / N
"); goto label2; } } } } // получение сообщений static void ReceiveMessage() { while (true) { try { string message = reader.ReadString(); Console.WriteLine(message);//вывод сообщения } catch { Console.WriteLine("Подключение прервано!"); //соединение было прервано Console.ReadLine(); Disconnect(); } } } static void Disconnect() { Console.WriteLine("disconect"); if (client != null) client.Close();//отключение клиента Environment.Exit(0); //завершение процесса } } }
Сервер - то же самое, с указанием той же кодировки:
using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Net; using System.Text; using System.Threading;
namespace ChatServer { public class ServerObject { static TcpListener tcpListener; // сервер для прослушивания List clients = new List(); // все подключения protected internal void AddConnection(ClientObject clientObject) { clients.Add(clientObject); } protected internal void RemoveConnection(string id) { // получаем по id закрытое подключение ClientObject client = clients.FirstOrDefault(c => c.Id == id); // и удаляем его из списка подключений if (client != null) clients.Remove(client); } // прослушивание входящих подключений protected internal void Listen() { try { tcpListener = new TcpListener(IPAddress.Any, 8888); tcpListener.Start(); Console.WriteLine("Сервер запущен. Ожидание подключений..."); while (true) { TcpClient tcpClient = tcpListener.AcceptTcpClient(); //Приём ожидающего запроса на подключение ClientObject clientObject = new ClientObject(tcpClient, this); Thread clientThread = new Thread(new ThreadStart(clientObject.Process)); clientThread.Start(); } } catch (Exception ex) { Console.WriteLine(ex.Message); Disconnect(); } } // трансляция сообщения подключенным клиентам protected internal void BroadcastMessage(string message, string id) { for (int i = 0; i < clients.Count; i++) { if (clients[i].Id != id) // если id клиента не равно id отправляющего { clients[i].SendMessage(message); //передача данных } } } // отключение всех клиентов protected internal void Disconnect() { tcpListener.Stop(); //остановка сервера
for (int i = 0; i < clients.Count; i++) { clients[i].Close(); //отключение клиента } Environment.Exit(0); //завершение процесса } } }
using System; using System.IO; using System.Net.Sockets; using System.Text;
namespace ChatServer { public class ClientObject { protected internal string Id { get; private set; } string userName; TcpClient client; ServerObject server; // объект сервера BinaryWriter writer;
public ClientObject(TcpClient tcpClient, ServerObject serverObject) { Id = Guid.NewGuid().ToString(); client = tcpClient; server = serverObject; serverObject.AddConnection(this); }
public void Process() { try { var stream = client.GetStream();
this.writer = new BinaryWriter(stream, Encoding.Unicode, false); var reader = new BinaryReader(stream, Encoding.Unicode, false); // получаем имя пользователя string message = reader.ReadString();
userName = message; string s = new String('*', 6); message = userName + " вошел в чат"; // посылаем сообщение о входе в чат всем подключенным пользователям server.BroadcastMessage(message, this.Id); Console.WriteLine(message); // в бесконечном цикле получаем сообщения от клиента while (true) { try { message = reader.ReadString(); if (message == "exit") { message = String.Format($"{s}{userName}: покинул чат{s}"); Console.Write(message); server.BroadcastMessage(message, this.Id); break;
} else { message = String.Format($"{userName}: {message}"); Console.WriteLine(message); server.BroadcastMessage(message, this.Id); } } catch { message = String.Format($"{s}{userName}: покинул чат{s}"); Console.Write(message); server.BroadcastMessage(message, this.Id); break; } } } catch (Exception e) { Console.WriteLine(e.Message); } finally { // в случае выхода из цикла закрываем ресурсы server.RemoveConnection(this.Id); Close(); } }
internal void SendMessage(string message) { this.writer.Write(message); }
public void Close() { if (client != null) client.Dispose(); } } }

воскресенье, 12 мая 2019 г.

Запуск приложения с помощью собственного протокола

На сетевом диске лежит приложение abc.exe. Как написать протокол, чтобы такая команда abc:\\param запускала это приложение с параметром param? Как пишется протокол? Все ли пользователи, имеющие доступ к шаре смогут использовать такой протокол или требуется на каждой машине требуется выполнить еще что-то?


Ответ

Протокол прописывается в реестре Windows.
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\yourprotocolname] @="URL:Direct Connect Protocol" "URL Protocol"=""
[HKEY_CLASSES_ROOT\yourprotocolname\Shell\Open\Command] @="cmd /c echo %1 & pause"
Обращаю внимание, что в браузере можно создавать ссылки на такой протокол. И таким ссылкам можно настроить автоматическое выполнение без запроса.
Поэтому очень важно отнестись к обработке передаваемых параметров внимательно. Например, определённый выше протокол с именем yourprotocolname представляет собой огромную дыру в безопасности, поскольку можно сделать что-то типа yourprotocolname:text & format d:
PS: Знаю, что в linux'е тоже возможно создавать кастомные протоколы, но не имею ни малейшего представления, как это делать.

вторник, 19 марта 2019 г.

Программа для видеозахвата

Задача такая. Необходимо создать приложение по наблюдению за кассирами. Существует база данных с операциями по кассирам, пробитие чека, аннулирование и т.д.
Была задумка по определенной выборке находить необходимые события по кассе, далее по событию находить нужный фрагмент видео в архиве, т.е. ориентироваться по времени чека(события) и вставать на фрагмент этого места в видео файле так же необходима возможность онлайн контроля процесса продажи.
Вопрос с чего начать, немного поискав понял что даже IP камеры несколько протоколов, а в наличии есть еще и аналоговые камеры... Возможно есть смысл онлайн контроль осуществлять с помощью какой то "бесплатной" готовой программы настроить чтобы программа могла писать в какой нибудь определенный распространенный формат AVI например.
А приложение уже писать самому и разбирать видео файлы, которые будут создаваться бесплатной программой.
желательно писать на C#, есть опыт.
с помощью какой библиотеки можно подружить камеры протокола rtsp с приложением C#(показывать видео онлайн, и писать его в архив)?


Ответ

с помощью какой библиотеки можно подружить камеры протокола rtsp с приложением C#(показывать видео онлайн, и писать его в архив)?
Посмотрите net7mma.codeplex.com
Проект активно развивается, и в сети довольно много упоминаний, включая EnSO, возможно эта библиотека перекроет ваши задачи.

пятница, 5 октября 2018 г.

Протокол для многопользовательской игры

Добрый день,
проект - многопользовательская игра, расчитаная на множество игроков (до 100), наподобие agar.io и тд. Сервер на C++, интерфейс - JavaScript (всё происходит внутри браузера). Стоит вопрос, как реализовывать передачу данных.
Идеи :
TCP - WebSocket UDP - разрабатывающийся "протокол" netcode.io (но ввиду того, что портируемость только на Windows, идея отброшена)
Уважаемые пользователи, может вы можете подсказать, как лучше сие реализовывать. А если уж WebSocket предлагаете, то какую библиотеку для него использовать в C++?


Ответ

Ну с протоколом вы уже определились в своем же вопросе.
Как лучше "сие" реализовать:
Для вас идеальный вариант (если это js клиент и c++ server и до 100 юзеров):
Библиотека: socket.io
Пример сервера на c++: c++ socket.io server
При правильном подходе и железе такой сервер выдержит не одну тысячу пользователей онлайн.