C# + .NET: Минималистичный пример асинхронного UDP

Однажды я экспериментировал с сетевым кодом в Unity3d.

Как вы, возможно, знаете, существуют различные системы, помогающие нам создавать сетевые приложения в Unity, с различными подходами и возможностями.

Однако, если вы более знакомы с обычным API сокетов и/или вам просто нужно портировать немного существующего кода, вам, вероятно, удобнее было бы разобрать простую отправку/получение данных.

Данная запись именно это и демонстрирует средствами .NET System.Net.Sockets.UdpClient:

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

namespace UdpTest {
    class Program {
        static void OnUdpData(IAsyncResult result) {
            // это то, что было передано в BeginReceive в качестве второго параметра:
            UdpClient socket = result.AsyncState as UdpClient;
            // указывает на того, кто отправил сообщение:
            IPEndPoint source = new IPEndPoint(0, 0);
            // получить сообщение и IP отправителя:
            byte[] message = socket.EndReceive(result, ref source);
            // здесь можно делать с `message` всё что хотите:
            Console.WriteLine("Got " + message.Length + " bytes from " + source);
            // ожидаем следующую операцию приема после завершения чтения:
            socket.BeginReceive(new AsyncCallback(OnUdpData), socket);
        }

        static void Main(string[] args) {
            UdpClient socket = new UdpClient(5394); // можно не указывать порт `new UdpClient ()` для автоматического выбора порта
            // ожидаем первую операцию получения:
            socket.BeginReceive(new AsyncCallback(OnUdpData), socket);
            // отправка данных (для простоты отправим обратно):
            IPEndPoint target = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5394);
            // отправить пару примеров сообщений:
             for (int num = 1; num <= 3; num++) {
                byte[] message = new byte[num];
                socket.Send(message, message.Length, target);
            }
            Console.ReadKey();
        }
    }
}

Используя этот подход, я смог создать сетевую систему в Unity, которая будет работать как для P2P-соединений между игровыми экземплярами, так и для подключения к внешним серверам.

Примечания:

  • Отправка в этом примере происходит синхронно, но практически ничего не теряет (запись в сокет не занимает много времени, особенно с учетом ограничений на размер датаграмм UDP).
  • AsyncResult.AsyncState может быть любого типа. В этом примере я использую его, чтобы легко получить сокет, на который пришли данные. Для более сложных систем может быть хорошей идеей создать "контекстный" класс, который будет содержать сам сокет (UdpClient) и любые другие значения, которые могут вам понадобиться.
  • Из-за текущих ограничений потоков в Unity у вас может не быть доступа к функциям, связанным с движком (unityengine.*). Чтобы обойти это, поместите полученные сообщения в какой-нибудь список, а затем обработайте их в методе обновления MonoBehaviour (Update).

Удачи!

Помощь с переводом от Terisback.

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.