NetSnake19
@NetSnake19
Студент, пока еще

Как исправить ошибку ложного подключения на стороне TcpClient?

Здравствуйте.

Решил сесть и повторить тему сетей, а сейчас перешел к сетевому программированию. Изучив некоторую базу в виде представления в c# ip адресов, сокетов и прочего, начал разбираться с классами TcpListener и TcpClient.

Суть вопроса

Определен простейший сервер в виде TcpListener на локальном хосте и конкретно взятом порте:
const int maxPartySize = 2;
var party = new List<TcpClient>();

var ip = IPAddress.Loopback;
var port = 50000;
var server = new TcpListener(ip, port);

server.Start();
Console.WriteLine("Сервер запущен..");

while (true)
{
	if (server.Pending() && party.Count < maxPartySize)
	{
		using TcpClient currentClient = await server.AcceptTcpClientAsync();
		party.Add(currentClient);
		Console.WriteLine($"Клиент {currentClient.Client.RemoteEndPoint} подключен. Текущий размер группы: {party.Count}");
	}
}


Также есть 3 экземпляра класса TcpClient, которые подключаются к указанному хосту через ip и порт, на которых работает сервер, описанный выше:
var destinationIp = IPAddress.Loopback;
var destinationPort = 50000;

var clients = new List<TcpClient>
{
        new TcpClient(),
	new TcpClient(),
	new TcpClient()
};

foreach (var c in clients)
{
	await c.ConnectAsync(destinationIp, destinationPort);

	if (c.Connected)
		Console.WriteLine($"Соединение с {c.Client.RemoteEndPoint} установлено.");
}


По какой то причине на стороне клиента отображается успешное подключение всех 3, несмотря на то, что физически подключено лишь 2. Корректную информацию о подключении отображает сервер, он подключает сначала первого, потом второго, на этом собственно все, как и должно быть из-за установленного лимита.
6593e6f14da93895024988.png

Почему так происходит? Может, стоит сделать ограничение на подключение другим способом?
  • Вопрос задан
  • 94 просмотра
Решения вопроса 2
NikFaraday
@NikFaraday
Student full-stack Developer
Попробуйте использовать более системный подход ограничения доступа через использования семафоров (SemaphoreSlim)

Второй момент, это подключение. То, что соединения установлено говорит лишь о том, что соединение с сервером ЕСТЬ, но это не значит, что в клиента есть доступ к ресурсам сервера. Для этого вы можете создать свои правила. Вы можете сообщить клиенту, что он находится в очереди и перед ним находится n клиентов.
Ответ написан
Комментировать
AshBlade
@AshBlade Куратор тега C#
Просто хочу быть счастливым
Для взаимодействия ты используешь TCP.
Connect() возвращается, когда установлено соединение, но само соединение все еще может находиться в очереди - то, что здесь и происходит.
Поэтому, лучше такое решение:

const int maxPartySize = 2;
var party = new List<TcpClient>();
var locker = new object();

var ip = IPAddress.Loopback;
var port = 50000;
var server = new TcpListener(ip, port);

server.Start(128);
Console.WriteLine("Сервер запущен..");

while (true)
{
    var client = await server.AcceptTcpClientAsync();
    _ = ProcessClientAsync(client);
    Console.WriteLine($"Клиент {client.Client.RemoteEndPoint} подключен. Текущий размер группы: {party.Count}");
}

async Task ProcessClientAsync(TcpClient client)
{
    await Task.Yield();
    bool added;
    lock (locker)
    {
        if (added = party.Count < maxPartySize)
        {
            party.Add(client);
        }
    }

    if (added)
    {
        Console.WriteLine($"Клиент {client.Client.RemoteEndPoint} добавлен в группу");
    }
    else
    {
        Console.WriteLine($"Клиент {client.Client.RemoteEndPoint} НЕ добавлен в группу");
    }
    
    client.Close();
}


P.S. когда принимаешь клиента не нужно писать using TcpClient client = ... иначе клиент закроется до начала его обработки
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы