Здравствуйте, пишу класс сервера, который мог бы обрабатывать несколько подключений. До этого никогда не писал. Использую TcpListener и TcpClient. После запуска TcpListener, каждое новый TcpClient сохраняется и в нём вызывается метод BeginRead, который, по-моему пониманию, будет ждать, пока на другом конце я не запишу строку в буфер, например, с помощью Write. Однако, работает не так, как ожидалось. BeginRead бесконечно считывает пустые строки, а при попытке выполнения Read со стороны клиента происходит ошибка: "Операция не разрешается на не подключённых сокетах" Совсем не понятно почему, ведь успешно выполнил команду Connect и не отключался.
Этот метод запускается в процессе сервера
public void Start()
{
try
{
TcpListener tcpListener = new TcpListener(IPAddress.Parse(ipAddress), port);
tcpListener.Start();
ServerLogger.Log("Server has been started");
while(true)
{
GameConnections.Add(new GameConnection(tcpListener.AcceptTcpClient(), GameConnections.Count));
}
}
catch(Exception ex)
{
ServerLogger.Error(ex.Message);
}
}
Создание подключения
class GameConnection
{
string GameID { get; set; }
string ConnectionID { get; set; }
TcpClient Client { get; set; }
byte[] acceptedData = new byte[1024];
byte[] sendData = new byte[1024];
byte[] buffer = new byte[1024];
NetworkStream stream;
public GameConnection(TcpClient client, int id)
{
Client = client;
stream = client.GetStream();
ConnectionID = "connection" + id;
ServerLogger.Log(string.Format("Client connected. ConnectionID: {1}", GameID, ConnectionID));
stream.BeginRead(acceptedData, 0, acceptedData.Length, FirstReadCallback, null);
}
public void FirstReadCallback(IAsyncResult ar)
{
int bytesRead = stream.EndRead(ar);
if(bytesRead > 0)
{
Console.WriteLine(bytesRead);
GameID = Encoding.UTF8.GetString(acceptedData, 0, bytesRead);
Console.WriteLine("Game id - " + GameID);
stream.BeginRead(acceptedData, 0, acceptedData.Length, ReadCallback, null);
ServerLogger.Log(String.Format("{0} game id is {1}", ConnectionID, GameID));
}else
{
ServerLogger.Log(String.Format("Empty first read from client({0})", ConnectionID));
stream.BeginRead(acceptedData, 0, acceptedData.Length, FirstReadCallback, null);
}
}
public void ReadCallback(IAsyncResult ar)
{
int bytesRead = stream.EndRead(ar);
if(bytesRead > 0)
{
string command = Encoding.UTF8.GetString(acceptedData, 0, bytesRead);
ServerLogger.Log(String.Format("Command from client({0}): {1}", ConnectionID, command));
string serverAnswer = "some game command";
Encoding.UTF8.GetBytes(serverAnswer, 0, serverAnswer.Length, sendData, 0);
stream.BeginWrite(sendData, 0, sendData.Length, WriteCallback, null);
}else
{
ServerLogger.Log(String.Format("Empty read from client({0})", ConnectionID));
stream.BeginRead(acceptedData, 0, acceptedData.Length, ReadCallback, null);
}
}
public void WriteCallback(IAsyncResult ar)
{
stream.EndWrite(ar);
stream.BeginRead(acceptedData, 0, acceptedData.Length, ReadCallback, null);
}
После того как сервер запущен пробую подключиться так:
static void Main(string[] args)
{
TcpClient client = new TcpClient();
try
{
Console.WriteLine("Connecting to server");
client.Connect(IPAddress.Parse("127.0.0.1"), 8888);
using (BinaryWriter writer = new BinaryWriter(client.GetStream()))
{
byte[] data = new byte[1024];
string gameID = "1000";
Encoding.UTF8.GetBytes(gameID, 0, gameID.Length, data, 0);
writer.Write(data, 0, gameID.Length);
Console.WriteLine(Encoding.UTF8.GetString(data));
}
while (true)
{
string command = Console.ReadLine();
if (command == "exit") break;
byte[] data = new byte[1024];
NetworkStream stream = client.GetStream();
using (BinaryWriter writer = new BinaryWriter(stream))
{
writer.Write(command);
}
using (BinaryReader reader = new BinaryReader(stream))
{
reader.Read(data, 0, 1024);
Console.WriteLine("Server answer: {0}", Encoding.UTF8.GetString(data));
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
client.Close();
}
}
По итогу в лог выглядит так:
Server has been started
Client connected. ConnectionID: connection0
connection0 game id is 1000
Empty read from client(connection0)
Empty read from client(connection0)
Empty read from client(connection0)
Empty read from client(connection0)
Empty read from client(connection0)
Empty read from client(connection0)
Empty read from client(connection0)
Empty read from client(connection0)
Empty read from client(connection0)
Empty read from client(connection0)
Empty read from client(connection0)
Empty read from client(connection0)
Как развивать веб-проекты в 2026 году: технологии, контент E-E-A-T и факторы доверия
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники