Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.70/30: Рейтинг темы: голосов - 30, средняя оценка - 4.70
0 / 0 / 0
Регистрация: 31.05.2017
Сообщений: 33

Серверный движок

31.05.2017, 12:52. Показов 6824. Ответов 80
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
привет у меня такой вопрос, делаю игру и пишу собственный серверный движок. подскажите в правильном ли я направлении двигаюсь? подойдет ли данный подход для написания своих серверов (чат, авторизация, игровой сервер)?
вот пример кода сервера авторизации который я набросал
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
 
namespace autorization
{
    class Program
    {
        static string log = null;
        static string pas = null;
 
        static void Main(string[] args)
        {
            start_server();
        }
 
        static void start_server()
        {
            // Устанавливаем для сокета локальную конечную точку
            IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8005);
 
            // Создаем сокет Tcp/Ip
            Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            // Назначаем сокет локальной конечной точке и слушаем входящие сокеты
            try
            {
                server.Bind(ipPoint);
                server.Listen(10);
                Console.WriteLine("Сервер запущен.");
                // Начинаем слушать соединения
                while (true)
                {
                    Console.WriteLine("Ожидаем соединение через порт {0}", ipPoint);
                    // Программа приостанавливается, ожидая входящее соединение
                    Socket client = server.Accept();
                    // Мы дождались клиента, пытающегося с нами соединиться
                    byte[] receive = new byte[1024];
                    for (int i = 0; i < receive.Length; i++) { receive[i] = 0; }
                    client.Receive(receive);
 
                    string message = Encoding.UTF8.GetString(receive);
                    //Указываем на конец строки с нужными данными
                    int count = message.IndexOf(";;;5");
                    if (count == -1) { continue; }
                    //Создаем переменную, в которой будет храниться очищенное сообщение
                    string clear_message = "";
                    for (int i = 0; i < count; i++) { clear_message += message[i]; }
                    //Начинаем делить очищенное сообщение на отдельные части
                    string[] split = clear_message.Split(':');
 
                    log = split[0];
                    pas = split[1];
 
                    Console.WriteLine("Подключение клиента: " + "Логин: " + log + " Пароль: " + pas);
 
                    if (log == "admin" && pas == "1234")
                    {
                        Console.WriteLine("Данные успешно подтверждены.");
                        // Отправляем ответ клиенту
                        string msg = "yes" + ";;;5";
                        byte[] send = new byte[1024];
                        send = Encoding.UTF8.GetBytes(msg);
                        client.Send(send);
                    }
                    else
                    {
                        Console.WriteLine("Указанные Логин или Пароль не найдены в Базе Данных.");
                        // Отправляем ответ клиенту
                        string msg = "no" + ";;;5";
                        byte[] send = new byte[1024];
                        send = Encoding.UTF8.GetBytes(msg);
                        client.Send(send);
                    }
 
                    Console.WriteLine("Сервер завершил соединение с клиентом.");
                    client.Shutdown(SocketShutdown.Both);
                    client.Close();
                }
            }
            catch (Exception ex) { Console.WriteLine(ex.ToString()); }
        }
    }
}
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
31.05.2017, 12:52
Ответы с готовыми решениями:

Серверный процесс
Здравствуйте! При старте программы, я создаю новый серверный процесс ( с помощью класса Process). По нажатию на кнопку я получаю от него...

Реализовать клиент-серверный чат (консольная версия)
Реализовать клиент-серверный чат (консольная версия) со следующими возможностями: • При подключении к серверу клиент получает...

Как переписать программу под серверный вариант
Добрый день. Подскажите как переписать(написать) прогу, чтобы установив ее на сервере, смогли работать клиенты на своих местах и еще чтобы...

80
Эксперт .NET
 Аватар для Usaga
14807 / 9580 / 1368
Регистрация: 21.01.2016
Сообщений: 36,086
02.06.2017, 08:24
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Dark Byte Посмотреть сообщение
Если уж работаешь с тасками - учи async/await и используй их, а не task.Start().
Хороший совет. Только нужно было обязательно уточнить, что async/await удобны только там, где используется одна фоновая задача. В случае с сервером, клиентов нужно обслуживать параллельно, а не по одному асинхронно (как позволяет делать async/await). Разница есть и она существенная.

Добавлено через 7 минут
Цитата Сообщение от wwworking Посмотреть сообщение
msg = "server ok".ToString()
Это вы для чего сделали? Что бы точно быть уверенным, что строка - это строка?))
0
0 / 0 / 0
Регистрация: 31.05.2017
Сообщений: 33
02.06.2017, 08:41  [ТС]
Usaga т.е. мне не слудует использовать task\async\await? возможно нужно использовать более низкоуровневую штуку , такую как: SynhronizationContext? или опуститься еще глубже до Invoke? но про инвоки написано что они только на винде работают(что-то в этом роде
Или использовать пул потоков? ThreadPool

Добавлено через 4 минуты
а может я просто забиваю себе голову и нужно было написать что-то типа
C#
1
2
Thread thread = new Thread(Working);
                    thread.Start();
Добавлено через 5 минут
или же вот какой вариант:
C#
1
ThreadPool.QueueUserWorkItem(Working);(код может быть не совсем правильным)
0
Эксперт .NET
 Аватар для Usaga
14807 / 9580 / 1368
Регистрация: 21.01.2016
Сообщений: 36,086
02.06.2017, 08:45
Цитата Сообщение от wwworking Посмотреть сообщение
т.е. мне не слудует использовать task\async\await?
Вам следует использовать task\async\await. Только перед этим нужно будет почитать про эти штуки и изучить их как следует, чтобы понимать где и как ими нужно пользоваться.

Добавлено через 1 минуту
Т.е. я рекомендую обзавестись пониманием происходящего и уже потом начинать пользоваться.
0
0 / 0 / 0
Регистрация: 31.05.2017
Сообщений: 33
02.06.2017, 08:48  [ТС]
Usaga ок)
0
Эксперт .NET
 Аватар для Usaga
14807 / 9580 / 1368
Регистрация: 21.01.2016
Сообщений: 36,086
02.06.2017, 08:52
wwworking, кстати, имей те в виду, что Task.Run использует тот же пул потоков, что и ThreadPool. Использование Task предпочтительнее, так как API там богаче и удобнее и оно с асинхронностью дружит (если надо).
0
0 / 0 / 0
Регистрация: 31.05.2017
Сообщений: 33
02.06.2017, 10:10  [ТС]
Usaga, Хороший совет. Только нужно было обязательно уточнить, что async/await удобны только там, где используется одна фоновая задача. В случае с сервером, клиентов нужно обслуживать параллельно, а не по одному асинхронно (как позволяет делать async/await). Разница есть и она существенная.
не пойму этот момент, если мы используем async/await то получится что все задачи описанные таким образом будут происходить асинхронно, но в главном потоке? а для сервера нам нужно создавать отдельные потоки, потому async/await нам не подойдут?(или как?)
0
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
02.06.2017, 10:14
Цитата Сообщение от wwworking Посмотреть сообщение
например если бы я написал this.login = login; ? в таком случае нужно было бы использовать this?
да
Цитата Сообщение от wwworking Посмотреть сообщение
ClientObject - зачем таки именовать класс? Почему не Client?
Не зачем. Но Client это слишком обще. Желательно добавить названию цель. Например если клиент VkApi то можно назвать VkClient.
Цитата Сообщение от wwworking Посмотреть сообщение
msg = "server ok".ToString(); - а зачем приводить стрингу к стринге?
Не зачем. Убирай. Ты что не сам писал код чтоли?
Цитата Сообщение от wwworking Посмотреть сообщение
Почему Account содержит msg? Какое это сообщение имеет отношение к аккаунту?
К тебе же вопрос. Если конечно ты сам писал код.
Цитата Сообщение от wwworking Посмотреть сообщение
Вместо объявления типа для каждой переменной, которая прямо в здесь и сейчас инициализируется, можно использовать var - это может повысить читабельность кода.
Это спорный вопрос. Везде по разному. Можешь писать если хочешь.
Цитата Сообщение от wwworking Посмотреть сообщение
while (true) - будет крутиться вечно?
да
Цитата Сообщение от wwworking Посмотреть сообщение
finally - сработает только при исключении, ведь из цикла нет выхода. Как я знаю, при закрытии приложения код в там не выполнится
finnaly сработает пусть хоть небо обрушится. Это блок который выполняется в любом случае.

Остальное вроде верно.
0
Эксперт .NET
 Аватар для Usaga
14807 / 9580 / 1368
Регистрация: 21.01.2016
Сообщений: 36,086
02.06.2017, 11:05
Цитата Сообщение от wwworking Посмотреть сообщение
не пойму этот момент, если мы используем async/await то получится что все задачи описанные таким образом будут происходить асинхронно, но в главном потоке? а для сервера нам нужно создавать отдельные потоки, потому async/await нам не подойдут?(или как?)
Грубо говоря да. Когда дело дойдёт до await текущий поток отправится выполнять что-то другое, а за дело возьмётся поток из IO-пула.

Таким образом можно оформлять только одну задачу "типа в параллель". Если нужна настоящая многозадачность, то тут только отдельные потоки.
0
0 / 0 / 0
Регистрация: 31.05.2017
Сообщений: 33
02.06.2017, 11:50  [ТС]
Usaga,для моего сервера как я понял мне нужны именно отдельные потоки, насчет Tasr.Run я не совсем понимаю как им пользоваться и что конкретно он выполняет, насчет пула потоков, я так понял что принцип его работы в следующем ( он как само-расширяющийся\сужающийся буфер. когда нам не хватает слотов для нового потока он его добавляет, а когда этот слот не нужен он его удаляет, приводя количество потоков к минимальному?)

Добавлено через 5 минут
Dark Byte, 1) а правильно-ли использовать такую конструкцию? this.login = login;
2)насчет msg = "server ok".ToString(); писал сам потому и накосячил )
3)Почему Account содержит msg? хз почему наверное не туда вставил, эта переменная должна выдавать ответ клиенту типа ОК
4)правильное-ли использование цикла while (true) или же нужно как-то по другому это дело проворачивать?. просто многие пишут что while (true) не есть хрошо
0
Эксперт .NET
 Аватар для Usaga
14807 / 9580 / 1368
Регистрация: 21.01.2016
Сообщений: 36,086
02.06.2017, 12:00
wwworking, Task.Run использовать очень просто:

C#
1
var task = Task.Run(() => { тут код, который будет запущен в потоке из пула });
Task.Run запускает задачу в отдельном потоке взятом из пула (строго оттуда же, откуда их берёт ThreadPool).
0
0 / 0 / 0
Регистрация: 31.05.2017
Сообщений: 33
02.06.2017, 12:07  [ТС]
Usaga, т.е. мне нужно будет написать следующие?:
C#
1
var task = Task.Run(() => { clientObject.Working});
вместо
C#
1
2
Task clientTask = new Task(clientObject.Working);
                    clientTask.Start();
0
Эксперт .NET
 Аватар для Usaga
14807 / 9580 / 1368
Регистрация: 21.01.2016
Сообщений: 36,086
02.06.2017, 12:39
wwworking, примерно так:

C#
1
2
3
4
5
var client = ... // получаем что-то описывающее клиента
...
var task = Task.Run(() => { ProcessClient(client) }); // запускаем отдельный поток с обработкой
...
// task можно использовать для определения и управления состоянием задачи (если нужно).
1
0 / 0 / 0
Регистрация: 31.05.2017
Сообщений: 33
02.06.2017, 12:46  [ТС]
Usaga, а откуда мы взяли ProcessClient?, домустим из моего кода
C#
1
2
3
4
5
6
TcpClient client = listener.AcceptTcpClient();
                    ClientObject clientObject = new ClientObject(client);
 
                    // создаем новый поток для обслуживания нового клиента
                    Task clientTask = new Task(clientObject.Working);
                    clientTask.Start();
получается что ваш client = моему clientObject. а вот чему будет равен ProcessClient?

Добавлено через 2 минуты
Usaga, получается что-ли так?
C#
1
var task = Task.Run(() => { Working(clientObject) });
?
0
Эксперт .NET
 Аватар для Usaga
14807 / 9580 / 1368
Регистрация: 21.01.2016
Сообщений: 36,086
02.06.2017, 12:49
wwworking, ну да, типа того. Лучше метод свой запускать отдельно и передавать ему объект, а он уже пускай с ним сам разбирается: хочет один метод вызовет, хоте - пять.
0
0 / 0 / 0
Регистрация: 31.05.2017
Сообщений: 33
02.06.2017, 12:52  [ТС]
Usaga, ну да, типа того. Лучше метод свой запускать отдельно и передавать ему объект, а он уже пускай с ним сам разбирается: хочет один метод вызовет, хоте - пять. это вы сейчас пишите про { Working(clientObject) }), на этом этаме метод забирает себе объект и делает с ним что захочет? я просто не до понял вас
0
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
02.06.2017, 12:58
Цитата Сообщение от wwworking Посмотреть сообщение
1) а правильно-ли использовать такую конструкцию? this.login = login;
Вполне
Цитата Сообщение от wwworking Посмотреть сообщение
4)правильное-ли использование цикла while (true) или же нужно как-то по другому это дело проворачивать?. просто многие пишут что while (true) не есть хрошо
Да это самый правильный способ организации бесконечного цикла имхо. Можно еще написать for (;;), но это на мой взгляд менее читабельно.
1
Эксперт .NET
 Аватар для Usaga
14807 / 9580 / 1368
Регистрация: 21.01.2016
Сообщений: 36,086
02.06.2017, 13:04
wwworking, да, запускайте в потоке свой метод и передавайте ему объект целиком, а там уже работайте с ним как надо.
0
0 / 0 / 0
Регистрация: 31.05.2017
Сообщений: 33
02.06.2017, 13:09  [ТС]
Dark Byte,сейчас у меня такой вот пирог и я думаю вот у меня в строке висит
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
class ClientObject
    {
        public TcpClient client;
        public ClientObject(TcpClient tcpClient)
        {
            client = tcpClient;
        }
        public void Working()
        {
            NetworkStream stream = null;
            try
            {
                stream = client.GetStream();
                BinaryReader reader = new BinaryReader(stream);
                //считываем данные их потока
                string lg = reader.ReadString();
                string ps = reader.ReadString();
                //создаем по полученным данным объект аккаунт
                Account account = new Account(lg, ps);
 
                Console.WriteLine("подключение клиента: {0}, пароль: {1}", account.log, account.pas);
 
                //отправляем ответ клиенту
                BinaryWriter writer = new BinaryWriter(stream);
                writer.Write(account.msg);
                writer.Flush();
 
                writer.Close();
                reader.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
 
            finally
            {
                if (stream != null)
                    stream.Close();
                if (client != null)
                    client.Close();
            }
        }
    }
C#
1
Console.WriteLine("подключение клиента: {0}, пароль: {1}", account.log, account.pas);
но эту строчку нужно будет заменить на обработку полученных данных (проверку их в бд), мне что придется писать метод внутри метода? или писать отдельно метод а потом этот новый метод вызывать внутри Working ? или же как-то по другому?

Добавлено через 3 минуты
Usaga, а что насчет строк
C#
1
2
TcpClient client = listener.AcceptTcpClient();
ClientObject clientObject = new ClientObject(client);
мне их оставить так как есть или же сделать как вы писали через var?
0
Эксперт .NET
 Аватар для Usaga
14807 / 9580 / 1368
Регистрация: 21.01.2016
Сообщений: 36,086
02.06.2017, 13:44
wwworking, var только для сокращения, уменьшает количество писанины, на функционале не сказывается. Использовать или нет, решать вам. Я использую.
0
0 / 0 / 0
Регистрация: 31.05.2017
Сообщений: 33
02.06.2017, 14:57  [ТС]
Usaga, Dark Byte, В общем вот что у меня на данный момент получилось:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.IO;
using System.Threading.Tasks;
using System.Net;
 
 
namespace server_login
{
    class AuthenPackage
    {
        public AuthenPackage(string Login, string Password)
        {
            this.Login = Login;
            this.Password = Password;
        }
        public string Login { get; private set; }
        public string Password { get; private set; }
    }
}
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.IO;
using System.Threading.Tasks;
using System.Net;
 
 
namespace server_login
{
    class UnityClient
    {
        public TcpClient client;
        public UnityClient(TcpClient TcpClient)
        { 
            client = TcpClient; 
        }
        public void ThreadHandler()
        {
            NetworkStream stream = null;
            try
            {
                stream = client.GetStream();
                using (var reader = new BinaryReader(stream))
                {
                    string login = reader.ReadString();
                    string password = reader.ReadString();
 
                    AuthenPackage package = new AuthenPackage(login, password);
 
                    Console.WriteLine("подключение клиента: {0}, пароль: {1}", package.Login, package.Password);
                }
                using (var writer = new BinaryWriter(stream))
                {
                    writer.Write("server ok");
                    writer.Flush();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
 
            finally
            {
                if (stream != null) stream.Close();
                if (client != null) client.Close();
            }
        }
    }
}
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.IO;
using System.Threading.Tasks;
using System.Net;
 
 
namespace server_login
{
    class Program
    {
        const int Port = 5006;
        static TcpListener server;
        static void Main(string[] args)
        {
            try
            {
                server = new TcpListener(IPAddress.Parse("127.0.0.1"), Port);
                server.Start();
 
                Console.WriteLine("Ожидание подключений...");
 
                while (true)
                {
                    TcpClient client = server.AcceptTcpClient();
                    UnityClient NewClient = new UnityClient(client);
 
                    var task = Task.Run(() => { ThreadHandler(NewClient); });
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                if (server != null) server.Stop();
            }
        }
 
        private static void ThreadHandler(UnityClient UnityClient)
        {
            throw new NotImplementedException();
        }
    }
}
к сожалению моя VS2010 не поддерживает фреймворк 4.5 для работы Task.Run, поэтому я пойду качать более позднюю версию, последнюю версию VS не могу использовать так как комп слабый =)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
02.06.2017, 14:57

Реализовать клиент серверный проводник для просмотра файлов на компьютере
Нужно реализовать клиент серверный проводник для просмотра файлов на компьютере. Вопрос : как возможно реализовать серверную часть, чтоб...

По нажатию на кнопку данные из input записываются в сессию+серверный редирект на другую страницу
На странице есть input(text) и кнопка. По нажатию на кнопку данные из input записываются в сессию+серверный редирект на другую страницу....

А кто сделал движок этого форума, потому что у многих русскоязычных форумов для программистов и не только движок похожий и кто его создал?
А кто сделал движок этого форума, потому что у многих русскоязычных форумов для программистов и не только движок похожий и кто его создал?

Серверный апгрейд
И так у меня на данный момент 350вт блок питания, материнка Asus P5QL SE S775, проц Dual Core E5200 2.5GHz, видюшка GeForce 9600GT...

серверный шкаф
здравствуйте, посоветуйте серверный шкаф для 2 серверов, 1 tower ш230 х д380 х в450 и HP 2)ш380 х д340х в100 фото серваков прикрепил,


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

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
Запустил конкурс "тем и промптов для текстовых квестов созданных почти чисто ИИ"
Adler 06.10.2026
Всем привет! За последние три-четыре дня я создал более 16 текстовых квестовых игр используя преимущественно по одному запросу к ИИ на игру. Мне так понравилось смотреть все ветки/ сцены во всех. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru