0 added
0 removed
Original
2026-01-01
Modified
2026-03-10
1
<p>Теги: telnet, tcp-сервер, создание сервера, с#, csharp, тср-клиент, онлайн-игры, клиент-серверное приложение, tcplistener, networkstream, client.connected</p>
1
<p>Теги: telnet, tcp-сервер, создание сервера, с#, csharp, тср-клиент, онлайн-игры, клиент-серверное приложение, tcplistener, networkstream, client.connected</p>
2
<p>Опишу самый простой способ создания<strong>TCP-сервера</strong>. Это сэкономит время и позволит получить быстрые результаты (я вообще люблю быстрые результаты).</p>
2
<p>Опишу самый простой способ создания<strong>TCP-сервера</strong>. Это сэкономит время и позволит получить быстрые результаты (я вообще люблю быстрые результаты).</p>
3
<p>Для создания простого синхронного сервера нам понадобится проект консольного приложения, поэтому использовать многопоточность не потребуется. Консольное приложение необходимо ещё и потому, что используемый код является блокировщиком потоков (<strong>thread-blocker</strong>). Это значит, что если вы создадите и запустите проект Windows Forms, вы не сможете перемещать и закрывать форму во время работы сервера, что неудобно.</p>
3
<p>Для создания простого синхронного сервера нам понадобится проект консольного приложения, поэтому использовать многопоточность не потребуется. Консольное приложение необходимо ещё и потому, что используемый код является блокировщиком потоков (<strong>thread-blocker</strong>). Это значит, что если вы создадите и запустите проект Windows Forms, вы не сможете перемещать и закрывать форму во время работы сервера, что неудобно.</p>
4
<p>Итак, код размещения<strong>ТСР-сервера</strong>выглядит следующим образом:</p>
4
<p>Итак, код размещения<strong>ТСР-сервера</strong>выглядит следующим образом:</p>
5
using System; using System.Text; using System.Net; // потребуется using System.Net.Sockets; // потребуется class Program { static void Main() { // устанавливаем IP-адрес сервера и номер порта 1234 TcpListener server = new TcpListener(IPAddress.Any, 1234); server.Start(); // запускаем сервер while (true) // бесконечный цикл обслуживания клиентов { TcpClient client = server.AcceptTcpClient(); // ожидаем подключение клиента NetworkStream ns = client.GetStream(); // для получения и отправки сообщений byte[] hello = new byte[100]; // любое сообщение должно быть сериализовано hello = Encoding.Default.GetBytes("hello world"); // конвертируем строку в массив байт ns.Write(hello, 0, hello.Length); // отправляем сообщение while (client.Connected) // пока клиент подключен, ждем приходящие сообщения { byte[] msg = new byte[1024]; // готовим место для принятия сообщения int count = ns.Read(msg, 0, msg.Length); // читаем сообщение от клиента Console.Write(Encoding.Default.GetString(msg, 0, count)); // выводим на экран полученное сообщение в виде строки } } } }<h2>Как это работает?</h2>
5
using System; using System.Text; using System.Net; // потребуется using System.Net.Sockets; // потребуется class Program { static void Main() { // устанавливаем IP-адрес сервера и номер порта 1234 TcpListener server = new TcpListener(IPAddress.Any, 1234); server.Start(); // запускаем сервер while (true) // бесконечный цикл обслуживания клиентов { TcpClient client = server.AcceptTcpClient(); // ожидаем подключение клиента NetworkStream ns = client.GetStream(); // для получения и отправки сообщений byte[] hello = new byte[100]; // любое сообщение должно быть сериализовано hello = Encoding.Default.GetBytes("hello world"); // конвертируем строку в массив байт ns.Write(hello, 0, hello.Length); // отправляем сообщение while (client.Connected) // пока клиент подключен, ждем приходящие сообщения { byte[] msg = new byte[1024]; // готовим место для принятия сообщения int count = ns.Read(msg, 0, msg.Length); // читаем сообщение от клиента Console.Write(Encoding.Default.GetString(msg, 0, count)); // выводим на экран полученное сообщение в виде строки } } } }<h2>Как это работает?</h2>
6
<p>Теперь давайте рассмотрим, как работает эта программа:</p>
6
<p>Теперь давайте рассмотрим, как работает эта программа:</p>
7
<ul><li>Мы подключаем для работы пространства имён<strong>System.Net</strong>и<strong>System.Net.Sockets</strong>.</li>
7
<ul><li>Мы подключаем для работы пространства имён<strong>System.Net</strong>и<strong>System.Net.Sockets</strong>.</li>
8
<li>Мы создаём сервер с помощью класса<strong>TcpListener</strong>, который будет слушать и принимать подключения с любого IP-адреса на указанном порту.:</li>
8
<li>Мы создаём сервер с помощью класса<strong>TcpListener</strong>, который будет слушать и принимать подключения с любого IP-адреса на указанном порту.:</li>
9
</ul>TcpListener server = new TcpListener(IPAddress.Any, 1234);<ul><li>Следующей строкой мы ожидаем и принимаем подключение от<strong>ТСР-клиента</strong>:</li>
9
</ul>TcpListener server = new TcpListener(IPAddress.Any, 1234);<ul><li>Следующей строкой мы ожидаем и принимаем подключение от<strong>ТСР-клиента</strong>:</li>
10
</ul>while (true) { TcpClient client = server.AcceptTcpClient(); ... }<ul><li>Клиент подключился и мы хотим отправить ему сообщение через<strong>NetworkStream</strong>. Однако мы не можем напрямую отправлять и получать строчки. Сообщение необходимо трансформировать в массив байт:</li>
10
</ul>while (true) { TcpClient client = server.AcceptTcpClient(); ... }<ul><li>Клиент подключился и мы хотим отправить ему сообщение через<strong>NetworkStream</strong>. Однако мы не можем напрямую отправлять и получать строчки. Сообщение необходимо трансформировать в массив байт:</li>
11
</ul>Encoding.Default.GetBytes("hello world");<ul><li>Отправляем полученный массив байт через<strong>NetworkStream</strong>:</li>
11
</ul>Encoding.Default.GetBytes("hello world");<ul><li>Отправляем полученный массив байт через<strong>NetworkStream</strong>:</li>
12
</ul>NetworkStream ns = client.GetStream(); ns.Write(hello, 0, hello.Length);<ul><li>Осталось получить сообщение от клиента - оно приходит в виде массива байт через тот же<strong>NetworkStream</strong>:</li>
12
</ul>NetworkStream ns = client.GetStream(); ns.Write(hello, 0, hello.Length);<ul><li>Осталось получить сообщение от клиента - оно приходит в виде массива байт через тот же<strong>NetworkStream</strong>:</li>
13
</ul>ns.Read(msg, 0, msg.Length);<ul><li>Осталось трансформировать массив в текстовую строчку и вывести её на экран:</li>
13
</ul>ns.Read(msg, 0, msg.Length);<ul><li>Осталось трансформировать массив в текстовую строчку и вывести её на экран:</li>
14
</ul>Console.WriteLine(Encoding.Default.GetString(msg).Trim());<p>Как видите, всё довольно просто.</p>
14
</ul>Console.WriteLine(Encoding.Default.GetString(msg).Trim());<p>Как видите, всё довольно просто.</p>
15
<h2>Сервер принимает только одного клиента. Почему?</h2>
15
<h2>Сервер принимает только одного клиента. Почему?</h2>
16
<p>Если мы внимательно посмотрим на исходник, всё становится понятно. Однако давайте всё же рассмотрим этот момент подробнее.</p>
16
<p>Если мы внимательно посмотрим на исходник, всё становится понятно. Однако давайте всё же рассмотрим этот момент подробнее.</p>
17
<p>У нас есть<strong>ТСР-клиент</strong>, который подключается к нашему серверу и отправляет данные. Пока<strong>client.Connected</strong>возвращает<strong>true</strong>, сервер будет заблокирован ожиданием новых сообщений и не сможет проверять/принимать новых<strong>ТСР-клиентов</strong>. Обычно этот вопрос решается созданием отдельных потоков для каждого подключённого клиента либо созданием асинхронного сервера, однако эти методы выходят за рамки нашей заметки.</p>
17
<p>У нас есть<strong>ТСР-клиент</strong>, который подключается к нашему серверу и отправляет данные. Пока<strong>client.Connected</strong>возвращает<strong>true</strong>, сервер будет заблокирован ожиданием новых сообщений и не сможет проверять/принимать новых<strong>ТСР-клиентов</strong>. Обычно этот вопрос решается созданием отдельных потоков для каждого подключённого клиента либо созданием асинхронного сервера, однако эти методы выходят за рамки нашей заметки.</p>
18
<p>Для проверки работы программы вы можете использовать<strong>Telnet</strong>, доступный в любой системе Windows. Для этого перейдите в командную строку и введите: telnet 127.0.0.1 1234. Если вы увидите сообщение “hello world”, напишите что-нибудь в ответ и нажмите<strong>Ctrl ]</strong>.</p>
18
<p>Для проверки работы программы вы можете использовать<strong>Telnet</strong>, доступный в любой системе Windows. Для этого перейдите в командную строку и введите: telnet 127.0.0.1 1234. Если вы увидите сообщение “hello world”, напишите что-нибудь в ответ и нажмите<strong>Ctrl ]</strong>.</p>
19
<p>На этом пока всё. Если хотите узнать больше о создании<strong>ТСР-серверов</strong>, записывайтесь на курс<a>Разработчик игр на С#</a>. Подробно рассмотрим технологии создания клиент-серверного приложения и разработаем онлайн-игру для мобильных телефонов.</p>
19
<p>На этом пока всё. Если хотите узнать больше о создании<strong>ТСР-серверов</strong>, записывайтесь на курс<a>Разработчик игр на С#</a>. Подробно рассмотрим технологии создания клиент-серверного приложения и разработаем онлайн-игру для мобильных телефонов.</p>
20
<p><em>Есть вопрос? Напишите в комментариях!</em></p>
20
<p><em>Есть вопрос? Напишите в комментариях!</em></p>
21
21