- 29
- 49
В этом гайде я покажу как создать соединение по вебсокету на базе SignalR с клиента LUA.
update 15.12.23. Теперь доступна библиотека для ванильных вебсокетов (любой сервер). Перейти
P.S В этом гайде будет использовано два языка программирования, поэтому некоторые моменты могут быть не понятны для тех кто кодит исключительно на LUA, но я постараюсь объяснить максимально понятно - как, что и почему. Читать далее или нет решать вам.
P.S.S Гайд будет на примере RakSamp
Что нужно для проекта:
1) Сервер вебсокет, в моем случае я буду использовать фреймворк SignalR от майкрософт.
2) Библиотека С++ для работы с соединением и получением информации.
3) LUA клиент.
Часть 1: Создание сервера
Я буду использовать C# ASP.NET, потому-что SignalR сервер может работать исключительно на .NET (хотя подсоединиться можно почти через что угодно). Плюс это удобно, в одном сервисе крутится вебсокет и обычный WEB-API (post, get ...).1)Открываем Visual Studio Installer
2) Находим Visual Studio 2022, жмем изменить
3)
2) Находим Visual Studio 2022, жмем изменить
3)
Открываем Visual Studio, нажимаем создание проекта, выбираем Веб-API ASP.NET CORE,
Жмем далее, настраиваем как на скрине
Создаем
Жмем далее, настраиваем как на скрине
Создаем
Если проект создан по спецификации выше, попадаем на класс Program. Это точка входа в наш веб-сокет сервер. Давайте удалим лишнее, вот такое должно получится:
Отредактированный текст:
var builder = WebApplication.CreateBuilder(args); //Создаем приложение
builder.Services.AddEndpointsApiExplorer(); //Говорим ему, чтобы слушал эндпоинты. Эндпоинт это конечный адрес, допустим есть адрес http://localhost:7229/Weather, эндпоинтом будет в нем Weather
var app = builder.Build(); //Применяем настройки выше
app.Run(); //Запускаем приложение
Изначально ASP.NET не подключает SignalR к проекту, поэтому это сделаем мы:
Подключение SIGNALR к проекту:
using Microsoft.AspNetCore.SignalR; //Добавляем пространство имен SignalR к проекту, после этого
//можем получить классы для работы с ним
var builder = WebApplication.CreateBuilder(args);
//Вообще, приложение ASP.NET состоит из сервисов, каждый отвечает за свою часть
builder.Services.AddEndpointsApiExplorer(); //Уже рассказывал
builder.Services.AddSignalR(); //Добавляем сервис SignalR
var app = builder.Build();
app.Run();
Теперь создадим класс для работы с сообщениями, в SignalR это называется Hub. Hub - принимает и отправляет сообщения, хранит данные о подключениях и т.д. Хабов в приложение может быть сколько угодно, они разделяют логику работы. Допустим в приложении есть чат, это будет ChatHub, и есть хаб уведомлений NotifyHub. У нас же будет
DataRecieverHub. Добавляем этот код в самый конец Program.cs.
DataRecieverHub:
internal class DataRecieverHub : Hub
{
//Тут будут обработчики
}
Хаб создан, хоть он и без каких-либо обработчков, формально он работает.
P.S Вообще на данном этапе я бы порекомендовал новичку изучить основы ООП (или глянуть ролик какой на ютубе). Потому что наш DataRecieverHub наследует (т.е перенимает некоторые свойства (переменные) и методы (функции)) от класса Hub. И уже содержит некоторые обработчики, просто они внутри Hub.
Чтобы приложение начало принимать данные в DataRecieverHub, нужно указать это в конфигурации, добавим эту строчку перед app.Run();
C#:
app.MapHub<DataRecieverHub>("data-reciever-hub");
Этой строкой мы говорим: если какой либо из клиентов пытается соединиться по ссылке http://localhost:7229/data-reciever-hub, значит отправляем его соединение в класс DataRecieverHub.
Добавим методы в DataRecieverHub. Обработчик подключения и отключения клиента:
Новые методы:
internal class DataRecieverHub : Hub
{
//Подключение, этот метод будет вызываться при подключении любого клиента
public override async Task<Task> OnConnectedAsync()
{
//Вызововем клиентский метод PendingMessage, на всех подключенных клиентах (включая того кто только подключился)
await Clients.All.SendAsync("PendingMessage", $"{this.Context.ConnectionId} is connected!");
//Базовый метод для подключения из Hub, вызываем его, если интересно можно почитать про полиморфизм в ООП
return base.OnConnectedAsync();
}
//Аналогично, только отключение
public override async Task OnDisconnectedAsync(Exception exception)
{
await base.OnDisconnectedAsync(exception);
}
}
Часть 2: Подключаемся к серверу
Как указано выше, я буду подключаться к серверу через раксамп, однако весь этот гайд так же подойдет для любых клиентов если там используется LUA5.1.Скачиваем библиотеку-прокладку из приложенного архива.
P.S
Для нормальной работы чистого луа не хватит, вообще основная причина написания этого гайда, то что готовыми библиотеками для вебсокетов (например lua websocket) обойтись в случае сампа скорее всего не получится. Мне пришлось создать библиотеку на С++ для луа, которая служит прокладкой между LUA и официальной библиотекой SignalR от майкрософт, она работает асинхронно, поэтому ничего блокировано не будет, о библиотеке-прокладке я расскажу в 3 части. Пока условимся что моя библиотека уже скачана и находится в папке /scripts/libs. Открытый код я так-же приложу далее.
Напишем простейший скрипт на LUA для подключения к нашему вебсокету:
Код подключения:
--Подключение библиотеки прокладки
require("WebS")
require("addon")
local encoding = require "encoding"
--Вызывается после успешной загрузки этого скрипта раксампом
function onLoad()
--Подключение к нашему эндпоинту
WebS.Connect("http://localhost:5056/data-reciever-hub");
--Бексконечный цикл получения сообщений с вебсокета.
newTask(function()
while true do
--Получаем последнее сообщение из очереди.
local output = WebS.GetMessage()
--Сообщение не пустое?
if output ~= '' then
print(output)
end
wait(100)
end
end)
end
function onDisconnect()
WebS.Disconnect()
end
Значит соединение прошло успешно. Боту присвоен уникальный идентификатор.
Теперь сделаем отправку сообщений на сервер из клиента LUA:
Добавим обработчик события onConnect в скрипт:
Отправка никнейма на сервер после подключения к серверу самп:
function onConnect()
local table = { getBotNick() }
WebS.SendMessage("BotConnected", table) -- BotConnect это имя метода (функции) из класса хаба ASP.NET, у нас его нет, поэтому добавим его
end
Добавим обработчик сообщения BotConnected для ASP.NET
Новые метод BotConnect:
internal class DataRecieverHub : Hub
{
public override async Task<Task> OnConnectedAsync()
{
await Clients.All.SendAsync("PendingMessage", $"{this.Context.ConnectionId} is connected!");
return base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception exception)
{
await base.OnDisconnectedAsync(exception);
}
//Добавленный метод
public async Task BotConnected(string botNick)
{
await Clients.All.SendAsync("PendingMessage", $"{botNick} success connected to server");
}
}
Хотелось бы уточнить как именно передаются данные из LUA на сервер, как видно метод WebS.SendMessage() принимает первым аргументом название метода из хаба который будет вызван, а вторым аргументом таблицу содержащую коллекцию строк (именно строк, не чисел и т.д)
Если бы мы хотели передавать помимо никнейма еще и пинг при подключении, надо сделать так:
ASP.NET:
C#:
public async Task BotConnected(string botNick, string ping)
{
await Clients.All.SendAsync("PendingMessage", $"{botNick} success connected to server with ping {ping}");
}
Lua:
function onConnect()
local table = { getBotNick(), tostring(getBotPing())}
WebS.SendMessage("BotConnected", table)
end
Часть 3: Библиотека-прокладка
Про библиотеку писать особо не вижу смысла, просто приложу исходникGitHub - memcpy1337/WebS: Библиотека-прокладка для работы с вебсокетами SignalR из LUA
Библиотека-прокладка для работы с вебсокетами SignalR из LUA - memcpy1337/WebS
github.com
Конец
Полный проект (РакСамп (https://www.blast.hk/threads/108052/) + ASP.NET) из гайда прикладываю в виде архива: СкачатьP.S Иногда библиотеки .dll надо положить в КОРЕНЬ раксампа (или гта са), т.е рядом с .exe.
P.S.S если ошибка осталась, и у тебя обычная гта с мунлоадером, положи WebS.dll в папку moonloader/lib, а содержимое папки sampwebsocket из архива, положи в корневую папки ГТА
Вложения
Последнее редактирование: