Форум администраторов игровых серверов

Форум администраторов игровых серверов (https://forum.zone-game.info/TT.php)
-   Программирование / Programming (https://forum.zone-game.info/forumdisplay.php?f=98)
-   -   С# клиент-сервер (https://forum.zone-game.info/showthread.php?t=38721)

kpNemo 20.06.2015 23:53

С# клиент-сервер
 
Доброго времени суток, господа. Есть ли у кого готовое решение на с# для получения и отправки информации, где одно приложение сервер-распространитель, а другое - клиент(-ы)? Искал, гуглил, читал на хабре, киберфоруме, и даже книжечку. Но видимо, ума не хватает.
Код:

static void Main(string[] args)
        {
            Data.Connect = "Database=bdworld;Data Source=localhost;User Id=root;Password=root";
            TcpListener server = null;
            try
            {             
                int MaxThreadsCount = Environment.ProcessorCount * 4;
                Console.WriteLine(MaxThreadsCount.ToString());
                // Максимальное количество рабочих потоков
                ThreadPool.SetMaxThreads(MaxThreadsCount, MaxThreadsCount);
                // Минимальное количество рабочих потоков
                ThreadPool.SetMinThreads(2, 2);


                // Порт для TcpListener = 9595.
                Int32 port = 9595;
                IPAddress localAddr = IPAddress.Parse("127.0.0.1");
                int counter = 0;
                server = new TcpListener(localAddr, port);
               
                    Data.parse_skills();
               
                // Запускаем TcpListener и начинаем слушать клиентов.
                server.Start();

                // Принимаем клиентов в бесконечном цикле.
                while (true)
                {
                    Console.Write("\nWaiting for a connection... ");
                    // При появлении клиента добавляем в очередь потоков его обработку.
                    ThreadPool.QueueUserWorkItem(ObrabotkaZaprosa, server.AcceptTcpClient()); 
                }
            }
            catch (SocketException e)
            {
                //В случае ошибки, выводим что это за ошибка.
                Console.WriteLine("SocketException: {0}", e);
            }
            finally
            {
                // Останавливаем TcpListener.
                server.Stop();
            }
        }

В обработке запросов(ObrabotkaZaprosa):
Код:

  static void ObrabotkaZaprosa(object client_obj)
        {
            try
            {
                // Буфер для принимаемых данных.
                Byte[] bytes = new Byte[256];
                String data = null;

                //Можно раскомментировать Thread.Sleep(1000);
                //Запустить несколько клиентов
                //и наглядно увидеть как они обрабатываются в очереди.
                //Thread.Sleep(1000);

                Data.client = client_obj as TcpClient;

                data = null;

                // Получаем информацию от клиента
                Data.stream = Data.client.GetStream();

                int i;

                // Принимаем данные от клиента в цикле пока не дойдём до конца.
                while ((i = Data.stream.Read(bytes, 0, bytes.Length)) != 0)
                {
                    // Преобразуем данные в ASCII string.
                    data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);

                    //В handling switch с определением что за сообщение, обработка его и возврат ответа в дату.
                    data = Data.handling(data);

                    // Преобразуем полученную строку в массив Байт.
                    byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);

                    try
                    {
                        // Отправляем данные обратно клиенту (ответ).
                        Data.stream.Write(msg, 0, msg.Length);
                    }
                    catch (Exception err)
                    { Console.WriteLine(err.ToString()); }

                }

                // Закрываем соединение.
                Data.client.Close();
            }
            catch { }

        }

Самое неприятное, что при очень быстром количестве запросов от клиента(раз в 100 мс) - сервер выпадает не удосужившись толком обьяснить в чём дело, ссылается на то, что было обращение к уже уничтоженным обьектам(самым разным). Может есть у кого готовое решение? Не могу до конца понять, как же всё-таки должен сервер общаться с клиентами. Код ужасен, помидорами кидайте, но помогите плс))

Zubastic 21.06.2015 00:09

Re: С# клиент-сервер
 
Зачем обращения раз в 100 мс?

kpNemo 21.06.2015 00:21

Re: С# клиент-сервер
 
Раз в 100 мс узнаю, есть ли новые сообщения для клиента. (чат, список игроков, к примеру)

DrHolmes 21.06.2015 01:03

Re: С# клиент-сервер
 
Если вы решили писать на C# - я бы предложил вам - взять за основу, кое что другое

Эмулятор полностью функционален, но заточен немного под другую игру, сама игра очень схоже по структуре с L2, ввиду того что использует движок почти той же версии что и L2, отсюда все(пакеты, игровой мир и прочее - не слишком разные)
Я правда не полностью уверен что там именно C#, возможно там C++ , и что-то от C#, но в любом случае это сурс - и может быть более удобной базой для разработки, по крайней мере не все нужно будет писать с нуля.

kpNemo 21.06.2015 01:26

Re: С# клиент-сервер
 
Цитата:

Сообщение от DrHolmes (Сообщение 396632)
Если вы решили писать на C# - я бы предложил вам - взять за основу, кое что другое

Эмулятор полностью функционален, но заточен немного под другую игру, сама игра очень схоже по структуре с L2, ввиду того что использует движок почти той же версии что и L2, отсюда все(пакеты, игровой мир и прочее - не слишком разные)
Я правда не полностью уверен что там именно C#, возможно там C++ , и что-то от C#, но в любом случае это сурс - и может быть более удобной базой для разработки, по крайней мере не все нужно будет писать с нуля.

А можно ссылочку? Если вы не против?

Нашёл решение(моя ошибка в создании нового подключения при каждом запросе, что вызывало ессно исключение, если подключение было в параллельном потоке закрыто(а обьект подключения статический)). И всё-таки, пока занимаюсь программирования - начинаю верить в "коллективный разум"! Уже не 1 и не 2 раза как замечаю. Только задаю вопрос знающим людям - через короткое время ответ приходит сам в голову, хотя до этого мог день возиться ошибкой. Будь-то не одна голова думала, будь-то ещё "приплюсовались процессоры", думающих над моим вопросом людей. Удивительно, но факт. Кому интерестно, сама суть ошибки:
ПРИМЕР ОДНОГО ИЗ ОБРАБОТЧИКОВ сообщения клиентом на отправку(получение сообщений в чат от сервера)
Код HTML:

  public static void GetChat()
        {
            TcpListener server = null;
            try
            {
                while (true)
                {
                    try
                    {
                        // Создаём TcpClient.
                        // Для созданного в предыдущем проекте TcpListener
                        // Настраиваем его на IP нашего сервера и тот же порт.

                        //Int32 port = 9595;                       
                        Data.client = new TcpClient(Data.server, Data.port);

                        // Переводим наше сообщение в ASCII, а затем в массив Byte.
                        Byte[] data = System.Text.Encoding.ASCII.GetBytes("(%3)" + Data.key);

                        // Получаем поток для чтения и записи данных.
                        Data.stream = Data.client.GetStream();

                        // Отправляем сообщение нашему серверу.
                        Data.stream.Write(data, 0, data.Length);
                        //Console.WriteLine("Sent: {0}", message);

                        // Получаем ответ от сервера.

                        // Буфер для хранения принятого массива bytes.
                        data = new Byte[256];

                        // Строка для хранения полученных ASCII данных.
                        String responseData = String.Empty;

                        // Читаем первый пакет ответа сервера.
                        // Можно читать всё сообщение.
                        // Для этого надо организовать чтение в цикле как на сервере.
                        Int32 bytes = stream.Read(data, 0, data.Length);
                        responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
                        //Console.WriteLine("Received: {0}", responseData);               
                        // Закрываем всё.
                        Data.stream.Close();
                        Data.client.Close();
                        if ((!responseData.Contains("hui")) && (responseData.Contains("(%3)")))
                        {
                            OPdata = new string[16, 100000];
                            responseData = responseData.Replace("(%3)", "");
                            /*string nick="";                           
                            for (int i = 0; i < responseData.Length; i++)
                            {
                                if (responseData[i] == '!')
                                {
                                    nick = responseData.Remove(i);
                                    Data.Chat.Add(responseData.Remove(0, nick.Length));
                                    break;
                                }
                            }*/
                            Data.Chat.Add(responseData);
                        }

                    }
                    catch { }
                    Thread.Sleep(100);
                }
            }
            catch { }
        }

Если данную ф-цию послать на выполнение в поток(и рядом в потоке подобную), то Data.client = new TcpClient(Data.server, Data.port); клиент вроде как будет пытаться сработать, но в отладчике уже будет видно готовое исключение для Data.stream = Data.client.GetStream(); Поэтому подключиться надо было всего один раз, при коннекте пользователя, после чего указанные строки удалить из других ф-ций. Спасибо, уважаемые форумчане! Коллективный разум решает!))

Zubastic 21.06.2015 05:25

Re: С# клиент-сервер
 
Цитата:

Сообщение от kpNemo (Сообщение 396631)
Раз в 100 мс узнаю, есть ли новые сообщения для клиента. (чат, список игроков, к примеру)

Раз 1-5 секунд вполне достаточно. Или вообще делать on event (при добавлении нового игрока в список идет пакет).

Necroz-Team 21.06.2015 08:49

Re: С# клиент-сервер
 
Предлагаю попробовать фреймворк Scs, _https://github.com/hikalkan/scs не реклама, удобная сеть, подходит как для серверной так и для клиентской части.

Sisi 21.06.2015 10:35

Re: С# клиент-сервер
 
:) мне вот интересно вы выбрали C# чисто из за знания данного языка или по каким то другим соображениям? Просто для меня имхо из C - C++ более адекватен...

kpNemo 21.06.2015 13:35

Re: С# клиент-сервер
 
Цитата:

Сообщение от Sisi (Сообщение 396641)
:) мне вот интересно вы выбрали C# чисто из за знания данного языка или по каким то другим соображениям? Просто для меня имхо из C - C++ более адекватен...

Работаю на с# на постоянной основе на дядю(разработка ПО для ВУЗов Украины и России) чуть больше года всего-то навсего, с++ знал, но год его не видел и позабыл аж не хочется вспоминать.


Текущее время: 16:54. Часовой пояс GMT +3.

Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot