при чтении из сокета - PullRequest
       8

при чтении из сокета

1 голос
/ 16 января 2012

Иногда при чтении сокета из TcpClient class поток поступает без мгновенной интерпретации данных. Например, если я подключаюсь к IRC-серверу и хочу интерпретировать текст в канале для распознавания команд. Если кто-то наберет команду, !time и !time - допустимая функция, она вернет на сервер текущее время.

Проблема в том, что если кто-то спамит эту же команду !time с высокой скоростью, сокет будет затоплен. Если кто-то еще попытается выполнить !time, он не будет выполнять обратную запись на сервер до тех пор, пока цикл while () не завершит чтение потока затопленных сокетов. Это может занять минуты, если не совсем, если пользователь продолжал рассылать спам / заливать команду.

static void Connect(String hostname, int port)
        {
            try
            {
                socket = new TcpClient(hostname, port);
                socket.ReceiveBufferSize = 4096;
                Console.WriteLine("Successfully connected to " + hostname);
                NetworkStream stream = socket.GetStream();
                reader = new StreamReader(stream);
                writer = new StreamWriter(stream);
                write("USER " + username + " 8 * :" + description, writer);
                write("NICK " + username, writer);
                write("NS IDENTIFY " + password, writer);//Authenticate account
                read(reader);//read the stream
                reader.Close();
                writer.Close();
                stream.Close();
                socket.Close();
            }
            catch
            {
                Console.WriteLine("Failed to connect to " + hostname);
            }
        }

функция read () ниже:

static void read(StreamReader reader)
        {
            try
            {
                while (true)
                {
                    interpret(reader.ReadLine());
                }
            }
            catch
            {
                Console.WriteLine("Unable to read from server");
            }
        }

Что я мог сделать, чтобы поток не пострадал, если бы он был затоплен? Так что, если кто-то затопит поток с помощью !time, это не помешает другим пользователям также видеть время, если они наберут !time.

Спасибо.

1 Ответ

1 голос
/ 16 января 2012

Решение Chatbot

Вам нужно будет обработать весь входящий текст хотя бы достаточно далеко, чтобы разделить сообщения, и определить, какой пользователь отправил каждое сообщение. Затем вы можете разделить их на отдельные очереди по пользователю. Вы можете обрабатывать очереди циклически или произвольно. Или можно реализовать схему сегментов памяти токенов, в которой каждые n секунд всем пользователям предоставляется определенное количество токенов, и каждая команда использует токен. Пользователям не разрешается превышать определенное количество токенов ( p секунд токенов, которые им разрешено копить). Если для пользователя нет токена при получении команды, либо выбросьте его, либо поставьте в очередь на следующий раз, когда токены будут выданы.


Серверное решение

У других пользователей есть свои собственные сокеты, не так ли?

Отставание в одном сокете не мешает вам читать другие. Вам просто нужно написать логику приложения, чтобы оно не зависало при чтении с одного, оно проходило циклически и считывало больше с первого раза, когда у каждого был шанс.

Обычно вы используете какую-то функцию, например select или WaitAny, которая выдает список готовых сокетов. Не всегда читайте из первого сокета в списке, выбирайте тот, который наиболее близко следует за последним, который вы прочитали, или выбирайте один случайным образом.

...