Форум » » C# и Websocket. Нужна помощь. » Ответить

C# и Websocket. Нужна помощь.

Paul_T: В C# пока полный 0, но изучать надо... Решил написать модуль для управления LG телевизора, работающий на Webos. Коммуникация ТВ осуществляется по Websocket на порт 3000. В библиотеках SIMPL# есть класс WebSocketClient, но мне показалось он несколько скуднее на методы, чем такой-же клас в библиотеках .NET. Ну да ладно, как я понимаю, сторонние библиотеки не прокатят и нужно пользоваться только теми, что описаны в SIMPL# (ну, кроме System, видимо). Написал клиентскую часть, соединение с сервером, получение клиентского ключа, сохранение ключа в файле, реализовал несколько команд управления. Работает! громкостью управляет, это уже хорошо, можно развивать дальше, но оказалось все не так просто. После простоя в минуту-две (отсутствие посылок клиент-сервер) сервер перестает отвечать на запросы, при этом метот Send(...) возвращает код WEBSOCKET_CLIENT_SUCCESS. Помогает только переподключение, т.е. нужно разорвать соединение и подключиться заново. За основу своего модуля брал простейший модуль написанный на JS, все сообщения соответствуют этому модулю. JS модуль работает в браузере без ограничения времени, поэтому предположу, что проблема не на стороне телеыизора. Но как ее найти, не понимаю... Может нужно делать асинхронное соединение? Но как это сделать методами SIMPL# так пока и не понял. Может кто сталкивался? Спасибо за любую помощь! PS. Еще заметил, что метод Read() выполняется бесконечно долго при отсутствии ответа от сервера. Может он имеет какие либо таймауты? Но я этого не нашел.

Ответов - 63, стр: 1 2 3 4 All

olegny: Paul_T пишет: Для этого, походу, придется писать свой WebSocketClient??? Зачем? Если вы сделаете как написано ниже, то поле GET в HTTP запросе будет пустое? https://stackoverflow.com/questions/10406930/how-to-construct-a-websocket-uri-relative-to-the-page-uri Например что-то типа: ws://192.168.1.121:3000/resources/c71caedade95e3bcb349163e36b3edcf368a534e/netinput.pointer.sock

Paul_T: В Simpl# URL и Port задается в свойствах. Там не получится написать такую конструкцию. Т.е. мы задаем свойства, а потом вызываем метод Connect() без аргументов... WebSocketClient Client; Client.URL = addressToConnectTo; Client.Port = port; WebSocketClient.WEBSOCKET_RESULT_CODES conn = Client.Connect(); ('string addressToConnectTo' и 'uint Port' я передаю из Simpl)

Paul_T: DmitriiP пишет: да и CrestronWebSocketClient это также не родной MS WebSocketClient а Simpl# обёртка В том то и дело, что приходится использовать Simpl# обертку (библиотеку) а не System.Net.WebSockets


olegny: 1. CrestronWebSocketClient никакая не обертка потому, что в .NET Compact Framework 3.5 нет System.Net.WebSockets. Подождите 4 Series где вас возможно выпустят из песочницы и резвитесь как хотите с полноценным Mono... )) 2. Какая разница как задаются элементы URI если в конечном итоге все это парсится и склеивается если надо. .Port, .Host и .URL в качестве URI это все, что вам нужно. Если поле в GET пустное, то значит ваш URL задан неправильно... Попробуйте задать 3000, 192.168.1.121 и /resources/c71caedade95e3bcb349163e36b3edcf368a534e/netinput.pointer.sock соответственно.

Paul_T: olegny пишет: Так некуда этот netinput.pointer.socket задавать. Я уже по всякому пробовал. Никак не хотет правильный запрос на подключение слать.. Зы. Кстати, крестрон 1 раз шлет Pong от балды, а потом молчит на Ping и сервер рвет соединение... Wireshark, кстати, расшифровывает пакеты websocket с маской. Что радует

olegny: Как это? Чисто через URL запихнуть не получается? Приведите все значения .Port, .Host и .URL и что получилось в результате в HTTP GET (wireshark?) Я посмотрю что там происходит на самом деле... P.S. Ну с PING/PONG там лажа. Это уже понятно! Надо чтобы кто-то зафалил им багу...

Paul_T: olegny пишет: .URL = "ws://192.168.1.121" .Port = 3000 .Host = тот URI, что приходит с сервера, но без "ws:" в начале ¨#þ¶¥X8¿XEJ@Ù´À¨'À¨yÂ÷ ¸ë=èÙÎP,'Ó GET / HTTP/1.1 Host: /resources/a4c087eb85bd01a0d46ed1e4b77d5e7dd15e7b02/netinput.pointer.sock Upgrade: websocket Connection: Keep-Alive, Upgrade Sec-WebSocket-Key: wngrQIV/pinlN7NXVwc3Pw== Sec-WebSocket-Version: 13 Host пишется отдельным Тэгом, не в GET

olegny: Ну и? Чего вы после этого ожидаете? ;) Попробуйте: .URL = тот URI, что приходит с сервера .Port = 3000 .Host = "192.168.1.121 И при этом выполните команду "SHOWEXTRA ENET ON" и пришлите "ERR SYS" с консоли.

Paul_T: olegny пишет: Да, меня это тоже смущало по началу. Но я соединяюсь с сервером и работают основные команды... Это уже второе подключение для клавиатуры и мышки. Если ws://192.168.1.121 писать в Host, то соединения нет ))) С тем запросом, что выше, соединение тоже устанавливается. Только не туда, куда надо... Из Хелпа "Set/Get Host is used in the Host field of the WebSocket handshake header. Do not add carriage return and line feed."

olegny: Не надо туда ws:// писать! )) В "err sys" все будет видно где ошибка...

Paul_T: olegny пишет: Если делать так: .URL = тот URI, что приходит с сервера .Port = 3000 .Host = "192.168.1.121 то вот: SYSTEM LOG: 1. Exception 'Data Abort' (4): Thread-Id=098401fa(pth=895e31b0), Proc-Id=05d1033a(pprc=86904000) 'splusmanagerapp.exe', VM-active=05d1033a(pprc=86904000) 'splusmanagerapp.exe' 2. PC=001cc9f8(???+0x001cc9f8) RA=00000000(???+0x00000000) SP=028efaa8, BVA=00000000 3. Info: splusmanagerapp.exe # 2019-04-20 12:32:59 # Close connection handle 79084d3e, reason 1000 4. Info: splusmanagerapp.exe # 2019-04-20 12:32:59 # WebSocket Client Error: error occured while closing ret=-1 Total Msgs Logged = 4 Не подключается, выскакивают исключения...

Paul_T: Немного опишу ход программы, а то мы уйдем в дебри. 1. Подключаюсь к серверу с такими параметрами: .URL = "ws://192.168.1.121" .Port = 3000 2. Проверяю ключ, что шлет сервер с тем, что хранится в файле 3. Все команды, что доступны при работе с основным подключением работают (громкость, каналы итд.) 4. Запрашиваю у сервера путь к сокету для 'мышки и клавиатуры". Он как раз присылает этот путь на сокет. До этого момента все работает как надо. Сервер отвечает на любые правильные запросы в JSON формате. Далее нам нужно 2 подключение с этим путем на Сокет. Т.е. фактически это 2-е websocket подключение. Которое пока не получается. Это подключение для отправки сообщений, которые уже идут не как JSON обьекты, а просто текстовые сообщения. Вот пока не получается подключиться как надо.

olegny: Пробуйте второе подключение как я описал выше. Удачи!

Paul_T: Попробовал. Не подключается вообще. Завтра попробую более основательно. Спасибо!!!

olegny: Ну тогда в .URL запихните все: ws://192.168.1.121:3000/resources/c71caedade95e3bcb349163e36b3edcf368a534e/netinput.pointer.sock плюс в .Host чистый 192.168.1.121, а в .Port = 3000

Paul_T: olegny пишет: Что бы я без Вас делал? Все верно! Для основного клиента я прописал: Client.Port = 3000; Client.Host = "192.168.1.121"; Client.ULR = "ws://192.168.1.121"; Таким образом, сервер при запросе URI на сокет возвращает: ws://192.168.1.121/resources/ec462d00ea95ca666f08d1e8043d0af61f6a0b9e/netinput.pointer.sock Соответственно для клиента 'Мышки": Mouse.Port = 3000; Mouse.Host = "192.168.1.121"; Mouse.Url = "ws://192.168.1.121/resources/ec462d00ea95ca666f08d1e8043d0af61f6a0b9e/netinput.pointer.sock" Т.е. ровно то, что вернул сервер. Теперь посылка для подключения к Сокету мышки выглядит так: ¨#þ¶¥X8¿XEq.@ÅÀ¨'À¨yÃB ¸EO©ç5@¸P,!¿ GET /resources/ec462d00ea95ca666f08d1e8043d0af61f6a0b9e/netinput.pointer.sock HTTP/1.1 Host: 192.168.1.121 Upgrade: websocket Connection: Keep-Alive, Upgrade Sec-WebSocket-Key: tm3oWM5IV2T7EIgK6mdWWA== Sec-WebSocket-Version: 13 И, да, ВСЕ работает!!! Осталось только слать PONG в "Сокет Мышки", т.к. сервер разрывает соединение ровно так-же как с основным Сокетом. Спасибо огромное! PS Теперь не совсем понимаю, как парсить ответы от сервера )))

olegny: Да, уж... PONG надо бы поправить им! Но вообще хорошо, а то было уже подумал, что у них там совсем лажа понаписана в клиенте... ;) А что там сервер возвращает-то?

Paul_T: olegny пишет: Кстати, с подключением похоже не все гладко. В логах сохраняется вот такое 1. Info: splusmanagerapp.exe # 2019-04-21 22:23:41 # WebSocketClientOpenSessionfc pURL: ws://192.168.1.121/ 2. Info: splusmanagerapp.exe # 2019-04-21 22:23:41 # WebSocketCopyClientRec: pURL ws://192.168.1.121/ 3. Info: splusmanagerapp.exe # 2019-04-21 22:23:41 # WebSocketURLConversion: ws://192.168.1.121/ 4. Info: splusmanagerapp.exe # 2019-04-21 22:23:41 # host:(null) ipaddr:192.168.1.121 path:/ 5. Info: CIPCommandProcessor.exe # 2019-04-21 22:23:42 # RetrieveSiteIPAddress: Cannot get hostname (ws://192.168.1.121/). Exception (No such host is known ) 6. Info: splusmanagerapp.exe # 2019-04-21 22:23:42 # WebSocketClientOpenSessionfc pURL: ws://192.168.1.121/resources/951f4d3368449969b9df87bf1f011a139744651a/netinput.pointer.sock 7. Info: splusmanagerapp.exe # 2019-04-21 22:23:42 # WebSocketCopyClientRec: pURL ws://192.168.1.121/resources/951f4d3368449969b9df87bf1f011a139744651a/netinput.pointer.sock 8. Info: splusmanagerapp.exe # 2019-04-21 22:23:42 # WebSocketURLConversion: ws://192.168.1.121/resources/951f4d3368449969b9df87bf1f011a139744651a/netinput.pointer.sock 9. Info: splusmanagerapp.exe # 2019-04-21 22:23:42 # host:(null) ipaddr:192.168.1.121 path:/resources/951f4d3368449969b9df87bf1f011a139744651a/netinput.pointer.sock 10. Info: CIPCommandProcessor.exe # 2019-04-21 22:23:43 # RetrieveSiteIPAddress: Cannot get hostname (ws://192.168.1.121/resources/951f4d3368449969b9df87bf1f011a139744651a/netinput.pointer.sock). Exception (No such host is known ) Как, говорил, задаю вот так: Client.URL = "ws://192.168.1.121; Client.Port = 3000; Client.Host = 192.168.1.121; Если URL задавать, как 192.168.1.121 или не задавать, то подключения не происходит. Кажется, что я уже попробовал все варианты, но может, что упустил. Надо еще раз попробовать попереставлять ))) Тем не менее подключения работают. Может, если сделать все правильно и PONG заработает? ))) Да нет, лажи у них нет. Это я просто ламмер ))). Пытаюсь освоить на начальном уровне... Что касается парсинга, я, вроде уже разобрался. Сервер может возвращать список каналов и приложений (среди которых, кстати входы и ТВ) в JSON формате: {"type":"response","payload":{"subscribed":false,"launchPoints":[{...},{...},{...},...,{...}}}; Из этого я получаю массив из JObject (элементы {...}б в которых куча ненужных и нужных элементов "id", "icon", "title" итд) JArray o = (JArray)JObject.Parse(rec_string)["payload"]["launchPoints"]; А, вот дальше мне нужно все это преобразовать в массив обьектов класса, который выглядит вот так: public class App { public string id { get; set; } public string icon { get; set; } public string title { get; set; } public string launchPointId { get; set; } } Получается несколько преобразований. string -> JArray -> поэлементно в string -> .net Object Мне кажется это не эффективно. Еще нарисовалась новая проблема))) В какой-то момент начинает все работать жутко медленно - начиная с подключения к серверу, заканчивая парсингом. Парсинг jArray длится 15 секунд. Почему это возникает пока не понятно. Все по началу вроде работает умеренно быстро, а потом "устает" Ps Пытаюст разобраться с асинхронной передачей, но пока ничего не понимаю. Да и примеров нет, близких к крестроновским методам...

olegny: В логе ничего страшного вроде нет, ибо это все только "info". Хотя, конечно, не понятно с чего бы вдруг CIP захотелось соединяться по указанному URL, но это наверное приколы Simpl+. Насчет неэффективности не знаю. Наверное можно что-то оптимизировать, но если работает и все успевает, то и фиг с ним... )) Парсить-то ведь как-то нужно все равно, но не вручную же! Когда начинает тормозить, посмотрите что там происходит следующими командами с консоли: RAMFREE CPULOAD (несколько раз) TASKSTAT

Paul_T: olegny пишет: Загрузка процессора 100% Причем 100 процентная загрузка возникает сразу после загрузки проекта. Т.е. без подкючения к websocket итд. App Name Proc ID Threads Heap Total/Used NK.EXE 0x00400002 93 3323416/2770104 udevice.exe 0x00FE0006 4 8192/5472 udevice.exe 0x01820006 1 8192/2496 udevice.exe 0x02C40002 1 8192/5056 udevice.exe 0x044C0002 4 36864/20032 udevice.exe 0x05150006 1 8192/2496 explorer.exe 0x051D0006 4 20480/12992 servicesd.exe 0x05830006 11 131072/92288 CrestronDllLoader.exe 0x067A0006 1 8192/1888 ConsoleServiceCE.exe 0x07520006 51 2052492/1910284 SystemCommandProcessor.exe 0x06280016 3 1089828/1000804 CRESLOG.exe 0x0702001A 5 159744/141344 SSHD.exe 0x07BE001A 4 249856/152576 TLDM.exe 0x061A001E 26 265764/234212 RfGateway.exe 0x07D0001E 158 332260/328612 CIPCommandProcessor.exe 0x08240002 14 1700212/1581908 CloudClient.exe 0x092C0006 10 2163076/1928932 CrestronTimerEventEngine.exe 0x087E000A 15 77880/67800 AutoUpdateInterface.exe 0x08CC000A 30 962788/911620 CustomAppManager.exe 0x094D000E 6 1138924/1058380 SimplSharpPro.exe 0x041F0026 25 3248804/3131780 LogicEngine.exe 0x085600B2 17 1726728/1715016 splusmanagerapp.exe 0x099C00E6 9 1745228/1661676 sftp-server.exe 0x084A0082 2 52168/40712 Спасибо огромное. Без Вас я бы еще месяц разбирался. А так фактически у меня все работает. Осталась только рутина ввиде описания всех необходимых команд, приведение всего в нормальный вид. Ну и понять асинхронное программирование ))).



полная версия страницы