Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.73/11: Рейтинг темы: голосов - 11, средняя оценка - 4.73
 Аватар для dev.nikor
29 / 30 / 3
Регистрация: 26.07.2010
Сообщений: 297
.NET 4.x

Оптимизация кода сервера (игра "Мафия")

12.06.2012, 14:52. Показов 2191. Ответов 5
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте, пишу сервер для игры мафия.
Я только начал, так что это ещё не весь код. Подскажите пожалуйста, можно ли его как-нибудь оптимизировать? Сервер пишу впервые.
Если вкратце, то создаю отдельный поток, в котором принимаю клиентов в бесконечном цикле, их добавляю в Queue для обработки и в List для посылания сообщений, всяких данных и т.д.
В основном потоке в бесконечном цикле, если Queue пуст, то ждем 100 миллисекунд и начинаем цикл с начала. Если Queue не пуст, то в отдельном потоке запускаю метод для его обработки.
Вот сам код:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
 
namespace Mafia_Server
{
    class Program
    {
        public static List<TcpClient> ClientList=new List<TcpClient>();  //Список подключённых клиентов
        public static Queue<TcpClient> ClientQueue=new Queue<TcpClient>();  //Для работы с клиентами
        private static TcpListener _bossHostListener;
        static void Main(string[] args)
        {
            _bossHostListener = Initializate(); //Возвращает TcpListener
            _bossHostListener.Start(10);
            Task clientAccepter=new Task(AcceptTcpClient); //Прослушиваем и принимаем в отдельном потоке
            clientAccepter.Start();
            while(true)
            {
                if(ClientQueue.Count==0)
                {
                    Thread.Sleep(100);
                    continue;
                }
                Task manageConnectionTask=new Task(ManagingConnections);
                manageConnectionTask.Start();
            }
        }
 
 
 
 
        /// <summary>
        /// Создаёт сокет
        /// </summary>
        /// <returns>Возвращает созданный сокет</returns>
        public static TcpListener Initializate()
        {
            Console.WriteLine("Вычисляю IP...");
            string hostIp = GetIpAddres();
            if (hostIp == "Error")
            {
                Console.WriteLine("Ошибка вычисления IP-адреса\n" +
                                  "Введите вручную (Пример: 192.168.0.1):");
                hostIp = Console.ReadLine();
            }
            try
            {
                IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(hostIp), 8000);
                TcpListener hostListener = new TcpListener(endPoint);
                Console.WriteLine("Подключаться на "+endPoint.Address+":"+endPoint.Port);
                return hostListener;
            }
            catch (SocketException socketException)
            {
                Console.WriteLine("Не удалось создать сокет (Error: {0}): {1}", socketException.ErrorCode, socketException.Message);
                TcpListener hostListener=new TcpListener(IPAddress.Any,8000);
                Console.WriteLine("Буду слушать все сетевые интерфейсы на 8000 порту");
                return hostListener;
            }   
        }
 
        /// <summary>
        /// Получает IP-адрес с [url]http://checkip.dyndns.org/[/url]
        /// </summary>
        /// <returns>IP-адрес</returns>
        private static string GetIpAddres()
        {
            try
            {
                string ip = null;
                WebRequest requesToMyIp = WebRequest.Create("http://checkip.dyndns.org/");
                WebResponse responseMyIp = requesToMyIp.GetResponse();
                Stream amFromMyIp = responseMyIp.GetResponseStream();
                if (amFromMyIp != null)
                {
                    StreamReader streamFromMyIp = new StreamReader(amFromMyIp);
                    ip = new Regex(@"(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})").Match(streamFromMyIp.ReadToEnd()).ToString();
                }
                return ip;
            }
            catch (Exception)
            {
                return "Error";
            }
        }
 
 
        /// <summary>
        /// Управляет получеными клиентами
        /// </summary>
        /// <param name="client">Клиент, с которым необходимо взаимодействие</param>
        public static void ManagingConnections()
        {
            if(ClientQueue.Count==0) return;
            TcpClient client = ClientQueue.Dequeue();
            if(client==null) return;
            Stream writerStream = client.GetStream();
            StreamReader readerStream=new StreamReader(client.GetStream());
            //тут потом будет код обработки
        }
 
 
        /// <summary>
        /// Асинхронно принимает клиентов и добавляет в List и Queue
        /// </summary>
        public static void AcceptTcpClient()
        {
            while (true)
            {
                Console.WriteLine("Ожидание новых подключений");
                TcpClient client = _bossHostListener.AcceptTcpClient();
                ClientList.Add(client);  
                ClientQueue.Enqueue(client);
                Console.WriteLine("//Новый клиент подключён");
            }
        }
    }
}
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
12.06.2012, 14:52
Ответы с готовыми решениями:

Простенькая игра мафия
Здравствуйте,хочу создать игру &quot;Мафия&quot;(Чтобы просто играть со знакомыми,хочу свой клиент,все сам настроить как хочу.), само собой,...

Игра Мафия
Как-то раз собрались n друзей, чтобы сыграть в «Мафию». В каждом раунде игры «Мафия» должен быть назначен ведущий (кто-то один из ребят),...

Игра, подобная шашкам. Оптимизация кода
Добрый вечер. У меня маленькая проблема: пишу игру, наподобие шашек. Почти готово, потом выложу исходники для критики. Сейчас делаю...

5
155 / 155 / 30
Регистрация: 19.10.2009
Сообщений: 319
12.06.2012, 16:28
Первое, на что хочется обратить внимание (даже не совсем оптимизация) - ни разу не вызывается метод Dispose, т. е. явно создаётся утечка памяти и прочие неосвобождённые ресурсы. Для этого есть оператор using, вот его пример:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
try
            {
                string ip = null;
                WebRequest requesToMyIp = WebRequest.Create("http://checkip.dyndns.org/");
                using (WebResponse responseMyIp = requesToMyIp.GetResponse())
                using (Stream amFromMyIp = responseMyIp.GetResponseStream())
          if (amFromMyIp != null)
          {
                    using (StreamReader streamFromMyIp = new StreamReader(amFromMyIp))
              ip = new Regex(@"(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})").Match(streamFromMyIp.ReadToEnd()).ToString();
          }
                return ip;
            }
            catch (Exception)
            {
                return "Error";
            }
Рекомендую просмотреть все методы, и где есть интерфейс IDisposable, не забывать его ставить.

Непосрественно по оптимизации. Если цель строк выше - просто узнать IP, то в классе DNS такой метод есть. Ожидание через Thread.Sleep - не лучший метод взаимодействия потоков. Лучше использовать EventWaitHandle, создать его можно с параметром ResetMode.Auto, в методе AcceptTcpClient делать Set, а в безымянном методе внутри Main вместо Thread.Sleep поставить его метод WaitOne. То что список клиентов только пополняется, но из него ничего не удаляется, полагаю, что временно, но важно не забыть где-то его и очищать, иначе оперативная память переполнится.
1
 Аватар для dev.nikor
29 / 30 / 3
Регистрация: 26.07.2010
Сообщений: 297
12.06.2012, 17:05  [ТС]
Цитата Сообщение от Ilya81 Посмотреть сообщение
Если цель строк выше - просто узнать IP, то в классе DNS такой метод есть.
Знаю, но он возвращает 6 адресов (у меня), 4 из которых IPv6 и 2 обычных - один локальный, другой глобальный

Цитата Сообщение от Ilya81 Посмотреть сообщение
Ожидание через Thread.Sleep - не лучший метод взаимодействия потоков.
Просто без этого сервер отъедает от процессора 1/4 (Core i5 2430m)

Цитата Сообщение от Ilya81 Посмотреть сообщение
Лучше использовать EventWaitHandle, создать его можно с параметром ResetMode.Auto, в методе AcceptTcpClient делать Set, а в безымянном методе внутри Main вместо Thread.Sleep поставить его метод WaitOne.
А не можете показать на примере, а то я не очень понимаю, что это значит
Цитата Сообщение от Ilya81 Посмотреть сообщение
То что список клиентов только пополняется, но из него ничего не удаляется
В процессе
0
155 / 155 / 30
Регистрация: 19.10.2009
Сообщений: 319
12.06.2012, 17:26
Собственно EventWaitHandle прямо здесь (с ним, думаю, сервер будет отъедать даже меньше процессора, чем с Thread.Sleep). Объявляем:
C#
1
private static EventWaitHandle _wait = new EventWaitHandle(ResetMode.Auto, false);
Ждём таким образом (за счёт этого и нагрузка на процессор сократится, что не будет выхода без необходимости):
C#
1
2
3
4
5
6
7
8
9
10
11
            while(true)
            {
                _wait.WaitOne();
                if(ClientQueue.Count==0)
                {
                    //Thread.Sleep(100); - это больше не нужно
                    continue;
                }
                Task manageConnectionTask=new Task(ManagingConnections);
                manageConnectionTask.Start();
            }
А отмашку даём так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
        public static void AcceptTcpClient()
        {
            while (true)
            {
                Console.WriteLine("Ожидание новых подключений");
                TcpClient client = _bossHostListener.AcceptTcpClient();
                ClientList.Add(client);  
                ClientQueue.Enqueue(client);
        _wait.Set();
                Console.WriteLine("//Новый клиент подключён");
            }
        }
1
 Аватар для dev.nikor
29 / 30 / 3
Регистрация: 26.07.2010
Сообщений: 297
12.06.2012, 19:32  [ТС]
Ilya81, а позволь спросить, в чём отличие между WaitHandle и EventWaitHandle?
0
155 / 155 / 30
Регистрация: 19.10.2009
Сообщений: 319
12.06.2012, 20:04
Вообще, WaitHandle, если посмотреть по документации - абстрактный класс, т. е. его экземпляр создать нельзя. EventWaitHandle наследуется от него, заодно с Mutex и Semaphore. Так что разницы меньше между Mutex и EventWaitHandle (если учесть, что класс Semaphore позволяет реализовывать количество объектов одновременного доступа больше единицы), по большому счёту у них только принципы использования разные. Но в самом WaitHandle есть ряд методов, скажем, WaitAll (это если б, например, нужно было б, чтоб пришли запросы с двух адресов/портов для обработки данных), для которых, соотвественно, годятся все наследуемые от него классы.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
12.06.2012, 20:04
Помогаю со студенческими работами здесь

Игра. Оптимизация кода. Динамические поля
Сделал игру для развития памяти. Код получился слишком большой и трудно в нем вносить правки. Плюс усложнить игру не представляется...

Игра в мафию, вероятность вытащить карту "мафия"
Всем привет! Возник следующий вопрос. Человек играет в мафию, где он каждую игру выбирает карту, он может достать карту &quot;мирного...

Оптимизация методом Ньютона (нахождение точки минимума). Оптимизация кода
MATLAB только начал осваивать. Попытался реализовать нахождение точки минимума методом Ньютона для функции 2*X12 - X1*X2 + 3*X22 -...

Оптимизация кода. Замер времени выполнения части кода.
Доброе утро. Есть желание посмотреть сколько времени занимает выполнение какого-то блока кода/отдельной функции или процедуры/программы...

Оптимизация сервера
Добрый вечер дорогие форумчаны. Как можно Оптимизировать сервер: Debian 5,ISP manager, ngixt. Характеристики сервера 500 mhz(4 ядра),...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru