Страницы

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

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

пятница, 20 марта 2020 г.

Android и NIST Internet Time Servers

#android #java #udp


Подскажите кто знает в чем может быть проблема?
Есть код: 
InetAddress address1 = InetAddress.getByName("nist.netservicesgroup.com");
int server_port = 123;
socket = new DatagramSocket();
byte[] buf = new byte[1024];
socket.setSoTimeout(10000);
DatagramPacket packet = new DatagramPacket(buf, buf.length, address1, server_port);
socket.send(packet);

DatagramPacket packet2 = new DatagramPacket(buf, buf.length);
socket.receive(packet2);

Отправляет на сервер nist.netservicesgroup.com порт 123 запрос. После чего ждет ответ
10 сек. 
Стоит permission android.permission.INTERNET.
Ответ не приходит. Ставил разные порты (13, 37 и 123). Менял разные адреса (список
тут http://tf.nist.gov/tf-cgi/servers.cgi)
Куда, что засунуть и откуда что высунуть чтобы заработало?
Заранее спасибо за полезные ответы.     


Ответы

Ответ 1



К сожалению, я не сталкивался с сокетами в андроиде и не работал с NIST. Из своего опыта с WinSock и сокетами на юникс-системах могу предложить использовать пятизначные порты, а также попробуйте настроить работу через стандартные способы, например через протокол tcp (т.к если назначения не существует, то сообщение просто не уйдет). Также проверьте доступность портов с другой стороны. У меня часто бывало, что сервер был выключен или работал на другом сокете. Незаменимым помощником будет браузер+ping+telnet (последнее я не использовал, но в различной литературе упоминается постоянно).

Ответ 2



вдруг кому пригодится, рабочий код: InetAddress address = InetAddress.getByName("nist.netservicesgroup.com"); int server_port = 37; Socket conn = new Socket(address1, server_port); InputStream in = conn.getInputStream();

среда, 29 января 2020 г.

Отправка данных через сокет (упаковка) с++

#cpp #linux #сокет #tcp #udp


Необходимо отправить данные типа:float/int/char через сокет, как организовать "упаковку"
на стороне отправителя что бы отправить всё одним пакетом, и "распаковать" на принимающей
стороне.

В сети нашёл скрин приложения для игры, как упаковать так же? 


    


Ответы

Ответ 1



Примитивный способ для простых случаев - описать структуру данных: struct Data { int a; float b; char c[32]; } data; Записать её в сокет на передающей стороне (send(socket, &data, sizeof(data), 0) и на принимающей прочитать в точно такую же структуру (recv(socket, &data, sizeof(data), 0)). Очень важно чтобы стуктура на обоих сторонах (передающей и приемной) была идентичной по расположению в памяти (одинаковые размеры типов, одинаковый порядок байтов в системе, одинаковое выравнивание полей структуры, одинаковое представление чисел с плавающей точкой). Иначе получаем не те данные, что отправили. На практике, если принимающая сторона ещё и на другом языке написана, получим лишнюю возню и простор для появления ошибок. Следующий вариант - набивать буфер данных вручную: int foo = 42; long bar = 0; std::string str; str.append((char*)&foo, sizeof(int)); str.append((char*)&bar, sizeof(long)); Здесь уже нет проблемы с выравниванием полей структуры как в первом варианте, т.к. данные мы склеиваем сами, без промежутков. Но остальные проблемы пока ещё с нами (по прежнему порядок байтов, размеры типов, представление чисел с плавающей точкой должны быть идентичными на передатчике и приемнике). Ручная, побайтовая набивка потока. uint32_t foo = 42; std::vector buffer; buffer.push_back(static_cast(foo >> 0)); buffer.push_back(static_cast(foo >> 8)); buffer.push_back(static_cast(foo >> 16)); buffer.push_back(static_cast(foo >> 24)); Здесь просто берем каждый кусок данных и вручную переносим в выходной поток в независимом от системы порядке. Разбирать тоже придется вручную. Наиболее универсальный способ, т.к. все аспекты генерируемого потока контролируем сами. Для удобства можно написать класс сериализатора/десериализатора для требуемых типов (включая пользовательские). Со временем (а может быть и сразу) добавляются сложности, связанные с изменением передаваемых данных (например понадобилось передать дополнительные данные или какие-то старые уже стали неактуальными). Особенно если приемник должен принимать данные и в старом формате и в новом. Придется добавлять какие-то идентификаторы версии. Дополнительно нужно обработать случаи, когда нужно передать опциональные данные (которые могут отсутствовать) или данные динамического размера (массивы). Чтобы не решать все эти задачи самостоятельно, можно взять готовое решение, например protobuf от google. Поддерживает разные языки, имеет систему версий, поддержку комплексных данных. Или немного более простое решение (но и более быстрое), тоже от google flatbuffers. Если объем передаваемой информации не критичен, возможно будет удобным формировать данные в виде json (например с помощью https://github.com/nlohmann/json). Если на принимающей стороне JavaScript программист, он будет вам очень благодарен (да и не только JavaScript программист). Также, как программисту из типизированного языка, рекомендую использовать схемы для проверки json. Как альтернативу json можно взять messagepack, который "как json", но компактнее. Если нужно ещё компактнее, можно пожать передаваемую строку с помощью zlib например. Для всех вариантов также надо учитывать, что передавать указатели бессмысленно, т.к. на принимающей стороне они будут указывать неизвестно куда. Также понимать тонкости передачи данных по сети. К примеру данные, отправленные по UDP, могут не дойти до получателя, данные отправленные по TCP могут быть фрагментированы или склеены с соседними при получении и т.п. Возможно стоит подумать о готовых сетевых библиотеках, например RakNet, которая включает в себя практически все для построения мультиплеерной игры.

Ответ 2



В функциях отправки данных на другой сокет (например, send) и функциях приема данных (например, recv) одним из параметров всегда является указатель на буфер с этими данными (байтами). Необходимо предварительно сформировать этот буфер. Сделать это можно очень разными способами. Например, если структура передаваемых данных динамическая и/или таких структур очень много, то можно формировать буфер, так сказать, "на лету". Т.е. мы нужные данные постепенно, по мере их получения, запихиваем в буфер. std::string buffer; uint32_t i32 = 0x32fe56ad; float f = 1.0; std::string str = "1234"; uint8_t sz = str.size(); buffer.append((char*)&i32, sizeof(i32)); buffer.append((char*)&f, sizeof(f)); buffer.append((char*)&sz, sizeof(sz)); buffer.append(str); std::cout << "lenght message: " <

Ответ 3



Правильным подходом будет использование сериализации данных. Например: Protocol Buffers, JSON, XML, ASN.1, и т.п. Сравнительная таблица.

среда, 22 января 2020 г.

C# UDP Отправка сервера к клиенту байт выдает ошибку

#c_sharp #сеть #udp


Всем привет! Когда сервер отправляет байт данных на уже отключенный клиент то я получаю
вот такое исключение:



Kак узнать клиент доступен ли?
Как утсранить эту проблему или обоити
?

Искал в интернете, нашел пару похожих вопросов но у них другие проблемы в конце решил
спросить тут.

Server:

        byte[] buffer = new byte[1024];
        IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
        IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 23000);
        Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

        EndPoint EP = (EndPoint)sender;

        int i;
        sock.Bind(ipep);

        while (true)
        {
            try
            {
                i = sock.ReceiveFrom(buffer, ref EP); // ошибка появляется здесь
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                Console.ReadKey();
                break;
            }

            // нажимаем на любую клаву чтобы получить ошибку
            Console.WriteLine("Нажмите любую клавишу чтобы отправить байт клиенту
и получить ошибку");
            Console.ReadKey();
            sock.SendTo(buffer, i, SocketFlags.None, EP);


Client:

        int serverPort = 23000;
        string hostName = "127.0.0.1";
        byte[] buffer = new byte[1024];

        EndPoint remote;
        IPEndPoint endPoint;
        Socket server;

        endPoint = new IPEndPoint(IPAddress.Parse(hostName), serverPort);
        server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);

        remote = (EndPoint)sender;

        buffer = Encoding.Unicode.GetBytes("me send");
        server.SendTo(buffer, 0, buffer.Length, SocketFlags.None, endPoint);

        // выходим из клиента чтобы сервер отправил отключенному клиенту;

    


Ответы

Ответ 1



Socket.ReceiveFrom внутри использует функцию recvfrom. Она соотвественно может завершится с ошибкой WSAECONNRESET(код у неё 10054). В документации на функцию recvfrom указанано следующие описание ошибки WSAECONNRESET: The virtual circuit was reset by the remote side executing a hard or abortive close. The application should close the socket; it is no longer usable. On a UDP-datagram socket this error indicates a previous send operation resulted in an ICMP Port Unreachable message. В кратце на русском: Если хост разорвет соединение и после этого будет вызыван send, то последующая операция чтения завершится с этой ошибкой. Соответственно чтобы решить вашу проблему, нужно использовать примерно такой код: static void Main(string[] args) { using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) { byte[] buffer = new byte[1024]; socket.Bind(new IPEndPoint(IPAddress.Any, 23000)); while (true) { var i = 0; EndPoint clientPoint = new IPEndPoint(IPAddress.Any, 0); try { i = socket.ReceiveFrom(buffer, ref clientPoint); } catch (SocketException ex) when (ex.ErrorCode == 10054) { // ни чего не делаем идем дальше continue; } catch (Exception ex) { Console.WriteLine(ex.ToString()); break; } socket.SendTo(buffer, i, SocketFlags.None, clientPoint); } } } PS: Есть еще магическая константа SIO_UDP_CONNRESET, которая вроде убирает генерирование этой ошибки. Но я не уверен, что она влияет только на этот случай поэтому код приводить с ней не буду.

понедельник, 23 декабря 2019 г.

Для чего нужен UDP, если он не гарантирует доставку?

#udp


Раз UDP протокол не гарантирует доставку пакетов или сегментов как там, то зачем
его вообще использовать?
    


Ответы

Ответ 1



Гарантия доставки далеко не всегда является основным критерием выбора протокола. Встает вопрос цены обеспечения этих гарантий. Протокол TCP требует установления соединения, этот процесс состоит из обмена тремя пакетами. После того как соединение установлено при передаче данных используются периодические подтверждения приема информации и повторные отправки, в случае если она не дошла. Для этого ядру операционной системы необходимо помнить состояние всех открытых TCP соединений и поддерживать буфера для принимаемой/передаваемой информации. А приложению необходимо для общения с каждым клиентом использовать отдельное соединение, при том что в большинстве ОC есть серьезные ограничения на количество одновременно открытых процессом дескрипторов файлов/соединений (часто всего 255 штук). А например Windows XP по умолчанию одновременно обслуживает не более 5 соединений, находящихся в стадии открытия. Да, UDP ничего не гарантирует, весь контроль на уровне приложения, зато это лечит все перечисленные выше минусы TCP. Рассмотрим некоторые применения UDP: Протокол назначения IP-адресов DHCP. Используется UDP так как в начале процесса у клиента еще нет IP и он не знает адреса сервера, который ему ответит. Поэтому необходимо использовать многоадресную рассылку без указания реального адреса отправителя. Мессенджеры. Требуется обмен короткими сообщениями с множеством клиентов. Зачастую недостаточно максимального количества открытых TCP соединений на процесс. Передавать информацию любому получателю с помощью одного общего сокета эффективное решение. Многоадресная рассылка: так как не требуется установление соединения с конкретным получателем то возможно использовать UDP при передаче multiсast/broadсast сообщений, т.е. сообщений предназначенных сразу многим получателям. Торрент клиенты. Так же как и мессанджерам требуется общаться с множеством получателей, при том что для установления необходимости дальнейшего взаимодействия достаточно обмена 2мя пакетами. При передаче файла порядок принимаемых фрагментов и потеря каких то из них не критична. Приложение само знает куда какой кусок положить и имеет поддержку докачки потерянного (возможно из других источников). SNMP (дословно: "Простой протокол управления сетью"). Используется повсеместно различным сетевым оборудованием. Используется UDP так как его реализация в железе значительно проще, чем TCP из за отсутствия необходимости поддерживать таблицы сессий и использовать для этого оперативную память, которой на устройстве может быть крайне мало. Передача потокового видео/голоса. У TCP есть серьезная проблема, при потере одного фрагмента приложению не будет передана никакая информация до тех пор пока потеря не будет компенсирована ядром OS. А для этого должен истечь таймаут ожидания пакета, отправлен запрос повтора и получен ответ. Такая задержка при передаче видео потока реального времени может быть не приемлемой. В то же время, т.к. в большинстве пакетов идут изменения к предыдущему опорному кадру потеря одного пакета приведет только к невозможности отразить изменения на небольшом участке, что не заметно для человеческого глаза. И когда передача пакета будет повторена в нем уже не будет необходимости, так как за это время уже отрисовано несколько последующих кадров. Приостановка же всего потока в ожидании повтора приведет к несколько секундной задержке всего изображения.

Ответ 2



Для гарантированного ответа TCP использует так называемое "тройное рукопожатие". Таким образом если среднее время, требуемое на отправку данных из точки А в точку Б составляет 10 мс, то для получения данных по TCP потребуется около 30 мс, в то время как по UDP не проводятся рукопожатия и время сокращается. Помимо времени протокол TCP использует больше служебной информации​. В некоторых случаях это критично, поэтому используют UDP. Например, на протоколе UDP работают торрент-клиенты. В них каждая часть файла подписывается и клиент получивший пакет проверяет нужен ли он ему или нет. UDP пакет может придти два раза, а может и не придти вовсе. Это основная разница, но есть конечно еще нюансы. Подробнее можете почитать здесь: http://thedifference.ru/chem-otlichaetsya-protokol-tcp-ot-udp/

Ответ 3



Производительность. Отсутствие лишнего, если хотят его реализовать сами. А еще "атипичность" решений - одна из методик защиты от реверс-инжиниринга. Что же касается гарантии доставки, то и с TCP тоже не все так просто. Вы же не думаете, что если вызвать stream.Write(byte[],int) и тут произойдет обрыв (достаточно длительный чтобы кончились несколько re-transmission), то будет выброшено исключение? Это не так, TCP асинхронен, поэтому исключение не выбросится, а только сокет в ОС установится в состояние "ошибка", а чтобы ваше приложение об этом узнало - нужно выполнить еще одно действие, обычно это чтение (ответа на отправленное), например в составе алгоритма типа Heart-beat или штатного Keep-Alive, который по сути делает то же самое, что Heart-beat. Действительно надежен только HTTP. Именно благодаря этому у него такой отрыв в популярности. Ну, и благодаря разным фичам тоже, но если мыслить глубже, то ясно, что это взаимосвязано. Источник: опыт разработки клиент-серверной системы на TCP, работающей 24/7/365, с максимальной надежностью и оперативностью информирования сервера о недоступных клиентах.

среда, 18 декабря 2019 г.

Производительный обмен сообщениями на QUdpSocket - возможно ли?

#cpp #qt #udp


Пытаюсь написать быструю кросплатформенную систему обмена сообщениями с гарантированной
доставкой на Qt, через QUdpSocket. Конечная цель - шина, промежуточная - издатель-подписчик,
начальная - "точка в точку". UDP - чтобы не тратить время на connect'ы. 

Структура такая: издатель ведёт список подписчиков, по каждому храня номер последнего
отправленного сообщения из кольцевой очереди. "Долбится" с этим сообщением, пока подписчик
не подтвердит, что успешно его принял, после чего издатель переходит к следующему.
Поскольку предполагается небольшое количество подписчиков, на каждого можно выделить
отдельный поток и работать блокирующими функциями. Поэтому издателей сделал перегрузкой
QThread, всю работу перенеся в run(). Подписчики ждут сигнала readyRead(), соответственно,
нуждаются в EventLoop. Поэтому подписчика унаследовал от QObject и перенёс в новый
QThread через moveToThread(). Вот основные куски кода:

void GQ::Subscriber::read()
{
    while(socket_.hasPendingDatagrams())
    {
        arr_.resize(socket_.pendingDatagramSize());
        socket_.readDatagram(arr_.data(),arr_.size(),&addr_,&senderPort_);
        QDataStream is(arr_);
        is>>number_;
        //qDebug()<<"<<"<itemByID(firstToSend);
        // Нет такого элемента
        while (!item.isNull())
        {
            firstToSend=item->ID;
            arr=GQ::toByteArray(*item.data());

            uint timeout=minTimeout;
            quint64 startTime=QDateTime::currentMSecsSinceEpoch();
            socket.write(arr);
            bool receivedOk=false;
            do
            {
                // Если за таймаут ничего не пришло - посылаем снова
                while (!socket.waitForReadyRead(timeout))
                {
                    qDebug()<<"Timeout, writing again";
                    socket.write(arr);
                    quint64 elapsed=QDateTime::currentMSecsSinceEpoch()-startTime;
                    qDebug()<<"Elapsed: "<(timeout*toutMultiplier))&&(timeout>number_;
//      qDebug()<<"<<"<


Ответы

Ответ 1



При вашей схеме все обработчики событий QEvent связанные с GQ::Publisher будут выполнятся в контексте потока в котором вы создали GQ::Publisher то есть, видимо, в главном потоке. Следовательно все они будут выполнятся синхронно. Вы скажете что вам они и не нужны, что вы специально от них уходили. А я вам отвечу, а кто вам сказал что события не используются внутри QUdpSocket к примеру? Вообще вы не совсем правильно используете QThread. Он не то чтобы поток сам по себе который исполняется асинхронно с другими, он скорее апартамент в понятиях COM. QThread нужен для того чтобы пробрасывать QEvent'ы так чтобы они обрабатывались синхронно но в контексте этого потока. Поэтому правильнее было бы GQ::Publisher отнаследовать от QObject, работу с сокетами и таймерами построить на сигналах/слотах. Ну и не забыть посадить паблишер в отдельный апартамент. То есть сделать GQ::Publisher так же как вы сделали подписчиков. Напомню что такое партаменты COM. В COM'е есть три потоковые модели: однопоточная, мультипоточная и апартаментная. Каждый объект COM обязан сообщать о модели которую он поддерживает. Потоковая модель это стандартизированный контракт который обязуются выполнять клиент и сервер. В однопоточной модели все вызовы к серверу синхронные потому что должны выполнятся из одного потока, в мультипоточной вызовы могут выполнятся полностью асинхронно из разных потоков, в апартаментной модели вызовы выполняются синхронно но из разных потоков. На самом деле там посложней все, но принцип думаю понятен.

Ответ 2



Решение найдено! Такая низкая скорость получается тогда, когда одна сторона bind'ит порт, а другая подключается через connect. Сообщения в сторону узла, не открывшего порт, идут почему-то очень медленно. Когда же я сделал bind на обеих сторонах и перешёл на простые readDatagram/writeDatagram, удалось добиться скорости порядка 70-80К сообщений на одном узле и 30-35К между узлами. То есть примерно 30% от ширины канала (Gigabit Ethernet), что для режима "запрос - ответ" я считаю приемлемым результатом. К сожалению, необходимость открывать порт на обеих сторонах усложняет архитектуру, ну да что-нибудь придумаем.

воскресенье, 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 г.

C# UDP Отправка сервера к клиенту байт выдает ошибку

Всем привет! Когда сервер отправляет байт данных на уже отключенный клиент то я получаю вот такое исключение:

Kак узнать клиент доступен ли? Как утсранить эту проблему или обоити ?
Искал в интернете, нашел пару похожих вопросов но у них другие проблемы в конце решил спросить тут.
Server:
byte[] buffer = new byte[1024]; IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0); IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 23000); Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
EndPoint EP = (EndPoint)sender;
int i; sock.Bind(ipep);
while (true) { try { i = sock.ReceiveFrom(buffer, ref EP); // ошибка появляется здесь } catch (Exception ex) { Console.WriteLine(ex.ToString()); Console.ReadKey(); break; }
// нажимаем на любую клаву чтобы получить ошибку Console.WriteLine("Нажмите любую клавишу чтобы отправить байт клиенту и получить ошибку"); Console.ReadKey(); sock.SendTo(buffer, i, SocketFlags.None, EP);
Client:
int serverPort = 23000; string hostName = "127.0.0.1"; byte[] buffer = new byte[1024];
EndPoint remote; IPEndPoint endPoint; Socket server;
endPoint = new IPEndPoint(IPAddress.Parse(hostName), serverPort); server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
remote = (EndPoint)sender;
buffer = Encoding.Unicode.GetBytes("me send"); server.SendTo(buffer, 0, buffer.Length, SocketFlags.None, endPoint);
// выходим из клиента чтобы сервер отправил отключенному клиенту;


Ответ

Socket.ReceiveFrom внутри использует функцию recvfrom. Она соотвественно может завершится с ошибкой WSAECONNRESET(код у неё 10054). В документации на функцию recvfrom указанано следующие описание ошибки WSAECONNRESET
The virtual circuit was reset by the remote side executing a hard or abortive close. The application should close the socket; it is no longer usable. On a UDP-datagram socket this error indicates a previous send operation resulted in an ICMP Port Unreachable message.
В кратце на русском: Если хост разорвет соединение и после этого будет вызыван send, то последующая операция чтения завершится с этой ошибкой.
Соответственно чтобы решить вашу проблему, нужно использовать примерно такой код:
static void Main(string[] args) { using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) {
byte[] buffer = new byte[1024]; socket.Bind(new IPEndPoint(IPAddress.Any, 23000));
while (true) { var i = 0;
EndPoint clientPoint = new IPEndPoint(IPAddress.Any, 0); try { i = socket.ReceiveFrom(buffer, ref clientPoint); } catch (SocketException ex) when (ex.ErrorCode == 10054) { // ни чего не делаем идем дальше continue; } catch (Exception ex) { Console.WriteLine(ex.ToString()); break; }
socket.SendTo(buffer, i, SocketFlags.None, clientPoint); } } }
PS: Есть еще магическая константа SIO_UDP_CONNRESET, которая вроде убирает генерирование этой ошибки. Но я не уверен, что она влияет только на этот случай поэтому код приводить с ней не буду.

пятница, 7 июня 2019 г.

Android и NIST Internet Time Servers

Подскажите кто знает в чем может быть проблема? Есть код: InetAddress address1 = InetAddress.getByName("nist.netservicesgroup.com"); int server_port = 123; socket = new DatagramSocket(); byte[] buf = new byte[1024]; socket.setSoTimeout(10000); DatagramPacket packet = new DatagramPacket(buf, buf.length, address1, server_port); socket.send(packet);
DatagramPacket packet2 = new DatagramPacket(buf, buf.length); socket.receive(packet2); Отправляет на сервер nist.netservicesgroup.com порт 123 запрос. После чего ждет ответ 10 сек. Стоит permission android.permission.INTERNET. Ответ не приходит. Ставил разные порты (13, 37 и 123). Менял разные адреса (список тут http://tf.nist.gov/tf-cgi/servers.cgi) Куда, что засунуть и откуда что высунуть чтобы заработало? Заранее спасибо за полезные ответы.


Ответ

К сожалению, я не сталкивался с сокетами в андроиде и не работал с NIST. Из своего опыта с WinSock и сокетами на юникс-системах могу предложить использовать пятизначные порты, а также попробуйте настроить работу через стандартные способы, например через протокол tcp (т.к если назначения не существует, то сообщение просто не уйдет). Также проверьте доступность портов с другой стороны. У меня часто бывало, что сервер был выключен или работал на другом сокете. Незаменимым помощником будет браузер+ping+telnet (последнее я не использовал, но в различной литературе упоминается постоянно).

понедельник, 29 октября 2018 г.

“Стрим” экрана (демонстрация экрана). Android API: MediaProjection

В официальном Android API написано следующее:
"Метод createVirtualDisplay позволяет вашему приложению записывать экран в объект Surface, который ваше приложение может отправить по сети."
У меня есть приложение, которое при нажатии на кнопку "Начать запись" начинает запись экрана.

При нажатии "Остановить запись" - останавливает.

При нажатии на "Play" - воспроизводит последнее видео, которое было записано.

Код я скопировал взял отсюда. Тут все вроде красиво и с объяснениями.
У меня есть сервер, написаный с помощью datagram сокетов, который принимает и возвращает пакеты.
Мой вопрос: как сделать "стрим" своего экрана (демонстрацию своего экрана)? Если делать это как-то через объект Surface, то как именно (есть ли примеры кода)?
P.S. Я читал в интернете что-то про Parcel.
Parcel – это контейнер для передачи данных.
Возможно ли его использовать для выполнения задачи?


Ответ

У меня получилось делать скриншоты и отправлять их. Сделал это через TCP. Вот. P.S. Приложение не доделано, но задача выполнена.

пятница, 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
При правильном подходе и железе такой сервер выдержит не одну тысячу пользователей онлайн.