В свое время делал клиента для Whats App, и многие приемы взяты оттуда. Но постоянно они что-то меняют. Плюс нельзя отправлять любые файлы, использовать клиента как web сервис и т.д.
Эта статья является продолжением статей
Использование сборок .NET в 1С 7.x b 8.x. Создание внешних Компонент
(Здесь же лежат и файлы клиентов и сервера)
И
В этой разработке используются обе эти разработки и служит примером того, как можно легко использовать технологии .Net в 1С.
В данной разработке можно обмениваться сообщениями,файлами, запрашивать данные от других клиентов. Клиенты могут быть как на 1С, так и с использованием вэб браузера, WPF приложения и даже андроид приложения и т.д.
Ну, начнем по порядку. Начну с кода на 1С.
Первое, что нам нужно, это подключиться.
Попытка
SignalRClietHello=Врап.ПолучитьТипИзСборки("SignalRClient.SignalRClietHello",Объект.КаталогDLL+"SignalRHelloClient.dll");
//Сборка=врап.загрузитьСборку(Объект.КаталогDLL+"SignalRHelloClient.dll");
Клиент=Врап.СоздатьОбъект(SignalRClietHello);
Клиент.Соединиться(Объект.АдресСервера).Wait();
фрм=ПолучитьФорму("ВнешняяОбработка.SignalRClient.Форма.ФормаОбработки");
ЗаполнитьЗначенияСвойств(Фрм.Объект,Объект,"АдресСервера,КаталогDLL,КаталогПолученныхФайлов,ИспользоватьСкомпилированнуюСборку");
Фрм.врап=врап;
Фрм.Клиент=Клиент;
фрм.Открыть();
Закрыть();
исключение
Сообщить(ОписаниеОшибки());
// ПоказатьПредупреждение(,Врап.ПоследняяОшибка.Message);
Врап.ВывестиПоследнююОшибку();
конецПопытки
При удачном подключении открываем форму обмена сообщениями
И добавим обработчики событий
&НаКлиенте
Процедура СоздатьОбертку(NetОбъект)
// Создаём обертку для событий и подключаем обработчики
//ОберткаСобытий=врап.СоздатьОберткуДляСобытий(NetОбъект);
// Можно использовать уже скомпилированную сборку, так как при
//врап.СоздатьОберткуДляСобытий создается файл ВрапперДляSignalRClient_SignalRClietHello.dll
ПолучитьОбертку(NetОбъект);
ДобавитьОбработчик ОберткаСобытий.ОшибкаСобытия,ОшибкаСобытия;
ДобавитьОбработчик ОберткаСобытий.ПриОтключении, ПриОтключении;
ДобавитьОбработчик ОберткаСобытий.ОшибкаСоединения, ОшибкаСоединения;
ДобавитьОбработчик ОберткаСобытий.ПриИзмененииСостоянияСоединения, ПриИзмененииСостоянияСоединения;
ДобавитьОбработчик ОберткаСобытий.ПриПолученииСообщения, ПриПолученииСообщения;
ДобавитьОбработчик ОберткаСобытий.ПриАвторизации, ПриАвторизации;
ДобавитьОбработчик ОберткаСобытий.ПриПолученииФайла, ПриПолученииФайла;
ДобавитьОбработчик ОберткаСобытий.ПриПодключенииНовогоПользователя, ПриПодключенииНовогоПользователя;
ДобавитьОбработчик ОберткаСобытий.ПриОтключенииПользователя, ПриОтключенииПользователя;
ДобавитьОбработчик ОберткаСобытий.ПриПолученииКоманды, ПриПолученииКоманды;
ДобавитьОбработчик ОберткаСобытий.ПриПолученииОтветаКоманды, ПриПолученииОтветаКоманды;
//NetОбъект==Клиент
Клиент.Зарегистрироваться(ИмяПользователя());
КонецПроцедуры
Не буду расписывать все обработчики, покажу только некоторые
/
/ параметр Данные:Аннимный Тип
// Свойства параметра
// id:System.String
// ИмяПользователя:System.String
// СписокПользователей:System.Collections.Generic.List`1[[SignalRClient.User, SignalRClient, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]
&НаКлиенте
Процедура ПриАвторизации(Данные)
пользователи=Элементы.Получатель.СписокВыбора;
пользователи.Очистить();
Элем=пользователи.Добавить("Всем","Всем");
ЭтотОбъект.Получатель="Всем";
Сообщить("ПриАвторизации "+Врап.ВСтроку(Данные));
ИД= Данные.id;
Для каждого Юзер Из Данные.СписокПользователей Цикл
ДобавитьНовогоПользователя(Юзер.ConnectionId, Юзер.Name)
КонецЦикла;
КонецПроцедуры
// параметр Данные:Аннимный Тип
// Свойства параметра
// ОтКого:System.String
// FileName:System.String
// id:System.String
// Данные:System.Byte[]
&НаКлиенте
Процедура ПриПолученииФайла(Данные)
Сообщить("ПриПолученииФайла "+Врап.ВСтроку(Данные));
Массив=Данные.Данные;
имяФайла =Врап.ПолучитьТип("System.IO.Path").Combine(Объект.КаталогПолученныхФайлов, Данные.FileName);
Врап.ПолучитьТип("System.IO.File").WriteAllBytes(имяФайла,Массив);
ДобавитьСообщение(Данные.ОтКого, "Отправлен файл "+ Данные.FileName, Данные.id, имяФайла);
Клиент.ОтправитьСообщение(СтрШаблон("Получен файл %1 размер %2 байт", Данные.FileName,Врап.ОбернутьЛюбойОбъект(Данные.Данные).Length), Данные.id);
КонецПроцедуры
// параметр Данные:Аннимный Тип
// Свойства параметра
// Имя:System.String
// сообщение:System.String
// IdОтправителя:System.String
&НаКлиенте
Процедура ПриПолученииСообщения(Данные)
Сообщить("ПриПолученииСообщения "+Врап.ВСтроку(Данные));
ДобавитьСообщение(Данные.Имя,Данные.сообщение,Данные.IdОтправителя,"")
КонецПроцедуры
Здесь применяются объекты и статические методы классов .Net, обернутые через врап=новый COMОбъект("NetObjectToIDispatch45");
Отправка сообщений происходит также через Net объект
&НаКлиенте
Процедура КомандаОтправитьСообщение(Команда)
// Вставить содержимое обработчика.
Если ПустаяСтрока(объект.Сообщение) Тогда
показатьПредупреждение(,"Сообщение не заполнено");
возврат
КонецЕсли;
ИДПолучателя=ЭтотОбъект.Получатель;
Если ПустаяСтрока(ИДПолучателя) Тогда
показатьПредупреждение(,"Не выбран получатель");
возврат
КонецЕсли;
Если Объект.ПоИмени и ИДПолучателя="Всем" Тогда
показатьПредупреждение(,"Нельзя отправлять по имени Всем");
возврат
КонецЕсли;
Сообщение=Объект.Сообщение;
Попытка
Если Объект.ПоИмени Тогда
Пользователи= Элементы.Получатель.СписокВыбора;
Имя=Пользователи.НайтиПоЗначению(ИДПолучателя).Представление;
// Можно отправлять ассинхронно без Wait
// Но могут быть проблемы с отловом ошибок
// На всякий случай поставим 1 сек ожидания
// для предотвращения взаимных блокировок
Клиент.ОтправитьСообщениеПоИмени(Сообщение,Имя).Wait(1000);
ИначеЕсли Получатель="Всем" Тогда
Клиент.ОтправитьСообщение(Сообщение, "").Wait(1000);
Иначе
Клиент.ОтправитьСообщение(Сообщение,ИДПолучателя).Wait(1000);
КонецЕсли;
Объект.Сообщение="";
исключение
Сообщить(ОписаниеОшибки());
Если Врап.ПоследняяОшибка<> Неопределено Тогда
ПоказатьПредупреждение(,Врап.ПоследняяОшибка.Message);
КонецЕсли;
КонецПопытки;
КонецПроцедуры
Реализованы следующие команды: КомандаОтправитьФайл, КомандаВычислитьСложение (отправляется команда и параметры клиенту, результат получается асинхронно).
Перейду с серверной части. Она написана на Asp.Net с использованием Nancy в котором кроме сервера SignalR реализован сайт с клиентом SignalR
Вот реализация Хаба
public class HelloHub : Hub
{
static List<User> Users = new List<User>();
bool ПользовательЗарегистрирован(User user)
{
var curId = Context.ConnectionId;
var имя = Users.Where(x => x.ConnectionId == curId).Select (x=>x.Name).SingleOrDefault();
user.Name = имя;
user.ConnectionId = curId;
return (!String.IsNullOrWhiteSpace(имя));
}
public void SendEcho(string str, string Кому)
{
var user = new User();
if (!ПользовательЗарегистрирован(user))
return;
if (string.IsNullOrWhiteSpace(Кому))
Clients.Others.addMessage(user.Name, str, user.ConnectionId);
else
Clients.Client(Кому).addMessage(user.Name, str, user.ConnectionId);
}
public void SendByName(string str, string Кому)
{
var user = new User();
if (!ПользовательЗарегистрирован(user))
return;
foreach(var клиент in Users.Where(x => x.Name.ToUpper() == Кому.ToUpper()).Select(x => x.ConnectionId))
Clients.Client(клиент).addMessage(user.Name, str, user.ConnectionId);
}
public void Send(string name2, string message)
{
var user = new User();
if (!ПользовательЗарегистрирован(user))
return;
Clients.All.addMessage(user.Name, message, user.ConnectionId);
}
public void SendFile(string Кому,string FileName, byte[] Data, bool isCompressed)
{
var user = new User();
if (!ПользовательЗарегистрирован(user))
return;
if (Users.Any(x => x.ConnectionId == Кому))
{
Clients.Client(Кому).GetFile(user.Name,FileName,user.ConnectionId,Data,isCompressed);
}
public void EvaluteCommand(string Кому,string command, byte[] Data, bool isCompressed)
{
var user = new User();
if (!ПользовательЗарегистрирован(user))
return;
if (Users.Any(x => x.ConnectionId == Кому))
{
Clients.Client(Кому).EvaluteCommand(user.Name,command,user.ConnectionId,Data, isCompressed);
}
}
public void ResultCommand(string Кому,string command,byte[] Data,bool isCompressed)
{
var user = new User();
if (!ПользовательЗарегистрирован(user))
return;
if (Users.Any(x => x.ConnectionId == Кому))
{
Clients.Client(Кому).ResultCommand(user.Name,command,user.ConnectionId,Data, isCompressed);
}
}
// Подключение нового пользователя
public void Connect(string userName)
{
var id = Context.ConnectionId;
if (!Users.Any(x => x.ConnectionId == id))
{
Users.Add(new User { ConnectionId = id, Name = userName });
// Посылаем сообщение текущему пользователю
Clients.Caller.onConnected(id, userName, Users);
// Посылаем сообщение всем пользователям, кроме текущего
Clients.AllExcept(id).onNewUserConnected(id, userName);
}
}
// Отключение пользователя
public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled)
{
var id = Context.ConnectionId;
var item = Users.FirstOrDefault(x => x.ConnectionId ==id);
if (item != null)
{
Users.Remove(item);
Clients.All.onUserDisconnected(id, item.Name);
}
return base.OnDisconnected(stopCalled);
}
}
Ссылки на SignalR Работа с SignalR
http://metanit.com/sharp/mvc5/16.1.php
Публикация вэб сервиса
http://professorweb.ru/my/ASP_NET/sites/level3/3_1.php
http://metanit.com/sharp/mvc/13.2.php
Файлы для публикации лежат в ..\SignalR\ФайлыДляПубликации\
Для сервера SignalR требуется сервер должен использовать Windows 8, Windows Server 2012 или более поздней версии, и WebSocket должен быть включен в IIS.
http://www.asp.net/signalr/overview/getting-started/supported-platforms
Попробовал поработать с Xamarin. В общем использовать можно, но еще сыро. Проще использовать WinMobile 10.
В папке SignalRMobile лежит недоделанный пример. Проблемы с инициализацией IOS модуля, ограничения на события с 4 мя параметрами и отсутствием времени не стал его доделывать.
В папке SignalRHelloClient лежит сборка для использования её в 1С
В папке SignalRClient лежит WPF приложение. Там же лежит основной модуль клиента SignalRClietHello.cs используемый обеими клиентами.
SignalRNancy это сервер.
Все файлы лежат по ссылке Использование сборок .NET в 1С 7.x b 8.x. Создание внешних Компонент
Для использования нужна .NET Framework 4.6
https://msdn.microsoft.com/Ru-ru/library/ms171868(v=vs.110).aspx
Для VS 2015 нужно обновление апдейт
Внешний отчет лежит в ВнешниеОтчеты\SignalRClient.epf
Написал статью на хабре по данной тематике ASP.NET Core, Angular 2, SignalR для чайников