Сокет клиент / сервер ввода / вывода опроса против чтения / записи в Linux - PullRequest
2 голосов
/ 23 июля 2010

По сути, я настроил тест, чтобы определить, какой метод является самым быстрым способом получения данных с другого компьютера в моей сети для сервера с несколькими клиентами (максимум 10, минимум 1).

Я попробовал два метода, оба были выполнены в потоке / для каждого клиента и повторили чтение 10000 раз. Я рассчитал цикл от создания потоков до объединения потоков сразу после. В своих потоках я использовал эти два метода, оба использовали стандартные вызовы read (2) / write (2) и SOCK_STREAM / AF_INET:

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

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

Я был почти уверен, что опрос будет быстрее. Я сделал гистограмму раз, чтобы завершить потоки, и, как и ожидалось, опрос был быстрее с небольшим запасом, но в методе чтения / записи не ожидалось двух вещей. Во-первых, метод чтения / записи дал мне два разных всплеска времени. И.Е. иногда происходило событие, которое замедляло чтение / запись примерно на 0,01 микросекунды. Сначала я запустил этот тест на коммутаторе и подумал, что это может быть коллизия пакетов, но затем я запустил сервер и клиент на одном компьютере и все еще получил эти два разных всплеска времени. Кто-нибудь знает, какое событие может происходить?

С другой стороны, моя функция чтения иногда возвращала слишком много байтов, и некоторые байты были мусором. Я знаю, что потоки не гарантируют, что вы получите все данные правильно, но почему функция чтения возвращает дополнительные байты мусора?

Ответы [ 2 ]

1 голос
/ 24 июля 2010

Кажется, вы путаете цель этих двух альтернатив:

  • Подход «соединение на поток» не требует опроса (если ваш протокол не допускает случайную последовательность сообщений в любом случае, что может быть очень сложно реализовать). Блокировка чтения и записи всегда будет быстрее, поскольку вы пропускаете один дополнительный системный вызов на select(2) / poll(2) / epoll(4).
  • Метод опроса позволяет мультиплексировать ввод / вывод на многих сокетах / файлах в однопоточном или фиксированном количестве потоков. Именно так веб-серверы, такие как nginx , обрабатывают тысячи клиентских подключений в очень небольшом количестве потоков. Идея состоит в том, что ожидание любого данного файлового дескриптора не блокирует другие - ожидание всех из них.

Так что я бы сказал, что вы сравниваете яблоки и гоблины :) Посмотрите здесь:

Что касается пиков - проверьте, входит ли TCP в режим повторной передачи, т. Е. Одна из сторон не читает достаточно быстро, чтобы истощить приемные буферы, поиграйте с опциями сокетов SO_RCVBUF и SO_SNDBUF.

Слишком много байтов определенно неверно - похоже на неправильное использование API - проверьте, сравниваете ли вы числа со знаком и без знака, компилируйте с высоким уровнем предупреждения.

Edit:

Похоже, вы находитесь между двумя отдельными проблемами - повреждение данных и производительность передачи данных . Я настоятельно рекомендую сосредоточиться на первом, прежде чем заняться вторым. Сократите тест до минимума и попытайтесь выяснить, что вы делаете неправильно с сокетами. то есть, откуда эти данные мусора. Вы проверяете возвращаемые значения вызовов read(2) и write(2)? Вы разделяете буферы между потоками? Вставьте уменьшенный пример кода в вопрос (или укажите ссылку на него), если он действительно застрял.

Надеюсь, это поможет.

0 голосов
/ 24 июля 2010

Я знаю, что потоки не гарантируют, что вы получите все данные правильно, но почему функция чтения возвращает дополнительные байты мусора?

На самом деле, потоки do гарантия, что вы получите все данные правильно и в порядке.Датаграммы (UDP) - это то, о чем вы думали, SOCK_DGRAM, а не то, что вы используете.В пределах AF_INET, SOCK_STREAM означает TCP, а TCP означает надежный.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...