Горячее
Лучшее
Свежее
Подписки
Сообщества
Блоги
Эксперты
#Круги добра
Войти
Забыли пароль?
или продолжите с
Создать аккаунт
Регистрируясь, я даю согласие на обработку данных и условия почтовых рассылок.
или
Восстановление пароля
Восстановление пароля
Получить код в Telegram
Войти с Яндекс ID Войти через VK ID
ПромокодыРаботаКурсыРекламаИгрыПополнение Steam
Пикабу Игры +1000 бесплатных онлайн игр Игра рыбалка представляет собой полноценный симулятор рыбалки и дает возможность порыбачить в реально существующих местах из жизни и поймать рыбу, которая там обитает.

Рыбный дождь

Спорт, Симуляторы, Рыбалка

Играть

Топ прошлой недели

  • dec300z dec300z 11 постов
  • AlexKud AlexKud 43 поста
  • DashaVsegdaVasha DashaVsegdaVasha 7 постов
Посмотреть весь топ

Лучшие посты недели

Рассылка Пикабу: отправляем самые рейтинговые материалы за 7 дней 🔥

Нажимая «Подписаться», я даю согласие на обработку данных и условия почтовых рассылок.

Спасибо, что подписались!
Пожалуйста, проверьте почту 😊

Помощь Кодекс Пикабу Команда Пикабу Моб. приложение
Правила соцсети О рекомендациях О компании
Промокоды Биг Гик Промокоды Lamoda Промокоды МВидео Промокоды Яндекс Маркет Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня
0 просмотренных постов скрыто
Darksoul11111
6 лет назад

Основа сервера для игры на C# с использование сокетов для работы с протоколом UDP.⁠⁠

Приветствую уважаемые подписчики! Как я вам и обещал, вот он переписанный сервер чата под игру. Все основные моменты в коде хорошо прокомментировал, если вдруг у вас возникнут вопросы, пишите в комментарии или пишите мне по указанным контактам внизу поста.


Сервер состоит из четырех классов: "Program.cs", "ServerObject.cs", "ClientObject" и "User.cs"


P.S. Shift + колесико мыши - листать код влево/вправо.


Program.cs:

Этот класс, запускает первый функционал сервера в отдельном потоке. Для того, что бы создать отдельный поток, необходимо подключить библиотеку "using System.Threading.Task;"


using System;

using System.Threading.Tasks;


namespace Realm

{

class Program

{

static void Main()

{

Console.Title = "Realm Server | ver. 0.1 beta alpha";

Console.WriteLine("Realm Server started...");

Console.WriteLine();


ServerObject server = new ServerObject();

Task serverTask = new Task(server.StartServer);

serverTask.Start();

serverTask.Wait();


Console.WriteLine("Realm Server stoped!");

Console.ReadKey();

}

}

}



ServerObject.cs:

Вы увидите в комментариях, такие слава как: "приема" и "подключенных", это - визуальное имитирование подключения клиентов к серверу, хотя на самом деле в функционале никакого подключения нет. Так же этот класс обеспечивает основной функционал сервера, такой как: рассылка сообщений другим клиентам, "подключение" новых клиентов к серверу.


using System;

using System.Collections.Generic;

using System.Text;

using System.Threading.Tasks;

using System.Net;

using System.Net.Sockets;

using System.Text.RegularExpressions;


namespace Realm

{

class ServerObject

{

private int acceptPort; // Порт для "приема" новых клиентов

public int receivePort; // Порт для приема сообщений от "подключенных клиентов"

private Socket listeningSocket; // Сокет для "приема" новых клиентов

private List<User> users = new List<User>(); // Список всех "подключенных" клиентов


/// <summary>

/// Запуск сервера

/// </summary>

public void StartServer()

{

Console.Write("Write port for accept users: ");

acceptPort = Int32.Parse(Console.ReadLine());

Console.Write("Write port for receive message: ");

receivePort = Int32.Parse(Console.ReadLine());

Console.WriteLine();


try

{

listeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); //
Создаем сокет

Task listenTask = new Task(Listen); // Создаем отдельный поток для метода

listenTask.Start(); // Запускаем поток

listenTask.Wait(); // Ожидаем завершения потока

}

catch(Exception ex)

{

Console.WriteLine("Error in StartServer(): " + ex.Message);

}

finally

{

StopServer(); // Останавливаем сервер

}

}


/// <summary>

/// Ожидание "подключений" к серверу

/// </summary>

private void Listen()

{

try

{

IPEndPoint acceptIP = new IPEndPoint(IPAddress.Parse("0.0.0.0"), acceptPort); // Создаем конечную точку на которую будут приходить сообщения

listeningSocket.Bind(acceptIP);


while(true)

{

StringBuilder builder = new StringBuilder();

int bytes = 0;

byte[] data = new byte[64];

EndPoint senderIP = new IPEndPoint(IPAddress.Any, 0);


do

{

bytes = listeningSocket.ReceiveFrom(data, ref senderIP);

builder.Append(Encoding.Unicode.GetString(data, 0, bytes));

}

while (listeningSocket.Available > 0 && Regex.IsMatch(builder.ToString(), "\\bCODE:[NAME]\\b") == true); // Удостоверяемся, что все данные получены и сообщение содержит метку означающее новое подключение


IPEndPoint senderFullIP = senderIP as IPEndPoint;


// Добавляем пользователя в список "подключенных"

bool addNewUser = true;

bool firstUser = false;


if(users.Count == 0)

{

AddUser(senderFullIP, builder);

firstUser = true;

addNewUser = false;

Console.WriteLine("First connected {0}:{1} his name - {2}", senderFullIP.Address.ToString(), senderFullIP.Port.ToString(), builder.ToString());

}


if (firstUser == false)

for (int i = 0; i <= users.Count; i++)

if (users[i].FullInfoIP.Address.ToString() == senderFullIP.Address.ToString())

addNewUser = false;


if(addNewUser == true)

{

AddUser(senderFullIP, builder);

Console.WriteLine("Connected {0}:{1} his name - {2}", senderFullIP.Address, senderFullIP.Port, builder.ToString());

}

}

}

catch(Exception ex)

{

Console.WriteLine("Error in Listen(): " + ex.Message);

}

finally

{

StopServer();

}

}


/// <summary>

/// Рассылка сообщений всем пользователям кроме одного

/// </summary>

/// <param name="message">Сообщение</param>

/// <param name="address">Адрес отправителя ( на этот адрес не будет отправлено сообщение )</param>

public void BroadcastMessage(string message, string address)

{

for(int i = 0; i < users.Count; i++)

if(users[i].FullInfoIP.Address.ToString() != address)

{

byte[] data = Encoding.Unicode.GetBytes(message);

listeningSocket.SendTo(data, users[i].FullInfoIP);

}

}


/// <summary>

/// Добавление клиента в список "подключенных"

/// </summary>

/// <param name="senderFullIP">Информация о новом клиенте</param>

/// <param name="builder">Сообщение клиента</param>

private void AddUser(IPEndPoint senderFullIP, StringBuilder builder)

{

User user = new User();

user.Id = Guid.NewGuid().ToString();

user.FullInfoIP = senderFullIP;

user.Name = builder.ToString();


users.Add(user);

ClientObject client = new ClientObject(this, user, receivePort);

}


/// <summary>

/// Запуск метода для прослушивания данного клиента в отдельном потоке

/// </summary>

/// <param name="client">Клиент для которого запускается отдельный поток</param>

public void UserIsAdded(ClientObject client)

{

Task clientTask = new Task(client.Listen);

clientTask.Start();

}


/// <summary>

/// Остановка сервера

/// </summary>

private void StopServer()

{

if (listeningSocket != null)

{

listeningSocket.Shutdown(SocketShutdown.Both);

listeningSocket.Close();

listeningSocket = null;

}

}

}

}

ClientObjcet.cs:

Данный класс обеспечивает получение сообщений от каждого "подключенного" пользователя, а после получения сообщения вызывает метод (server.BroadcastMessage()) для рассылки этого сообщения всем остальным "подключенным" клиентам.


using System;

using System.Text;

using System.Net;

using System.Net.Sockets;


namespace Realm

{

class ClientObject

{

ServerObject server;

User user;

int receivePort; // Порт который будет принимать сообщения от данного клиента


public ClientObject(ServerObject _server, User _user, int _port)

{

server = _server;

user = _user;

receivePort = _port;

server.UserIsAdded(this);

}


/// <summary>

/// Прием сообщений от конкретного пользователя

/// </summary>

public void Listen()

{

Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

IPEndPoint receiveIP = new IPEndPoint(IPAddress.Parse("0.0.0.0"), receivePort);

socket.Bind(receiveIP);


while(true)

{

StringBuilder builder = new StringBuilder();

int bytes = 0;

byte[] data = new byte[64];

EndPoint senderIP = new IPEndPoint(user.FullInfoIP.Address, user.FullInfoIP.Port);


do

{

bytes = socket.ReceiveFrom(data, ref senderIP);

builder.Append(Encoding.Unicode.GetString(data, 0, bytes));

}

while (socket.Available > 0);


Console.WriteLine("{0}: {1}", user.Name, builder.ToString());

server.BroadcastMessage(builder.ToString(), user.FullInfoIP.Address.ToString());

}

}

}

}

User.cs

А этот класс служит в качестве структуры клиента.


using System.Net;


namespace Realm

{

class User

{

public string Id { get; set; }

public IPEndPoint FullInfoIP { get; set; }

public string Name { get; set; }

}

}


Контактные данные:
Телега - https://tele.gg/prog_and_mod

Или

@prog_and_mod

Показать полностью
Unity Основа сервера Gamedev Csharp Длиннопост Текст
13
Посты не найдены
О нас
О Пикабу Контакты Реклама Сообщить об ошибке Сообщить о нарушении законодательства Отзывы и предложения Новости Пикабу Мобильное приложение RSS
Информация
Помощь Кодекс Пикабу Команда Пикабу Конфиденциальность Правила соцсети О рекомендациях О компании
Наши проекты
Блоги Работа Промокоды Игры Курсы
Партнёры
Промокоды Биг Гик Промокоды Lamoda Промокоды Мвидео Промокоды Яндекс Маркет Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня
На информационном ресурсе Pikabu.ru применяются рекомендательные технологии