Включает ли поток TCP, содержащий SYN и ACK, только один -временной пакет Ethernet?

Вот альтернативный метод и небольшой бенчмаркинг, добавленный к этому в ответе Weijun Zhou .

join

Предполагая, что у вас есть файл data, из которого вы хотите извлечь строки, и файл line_numbers, в котором перечислены номера строк, которые вы хотите извлечь, если порядок сортировки вывода не важен, вы можете использовать:

join <(sort padded_line_numbers) <(nl -w 12 -n rz data) | cut -d ' ' -f 2-

Это пронумерует строки вашего файла data, соединит его с файлом padded_line_numbersв первом поле (по умолчанию )и распечатает общие строки (, исключая само поле соединения, что вырезано ).

joinтребует, чтобы входные файлы были отсортированы по алфавиту. Вышеупомянутый файл padded_line_numbersдолжен быть подготовлен путем заполнения слева -каждой строки вашего файла line_numbers. Например.:

while read rownum; do
    printf '%.12d\n' "$rownum"
done padded_line_numbers

Опции и аргументы -w 12 -n rzпредписывают nlвыводить 12-значные числа с ведущими нулями.

Если порядок сортировки вывода должен совпадать с порядком сортировки вашего файла line_numbers,вы можете использовать:

join -1 2 -2 1 <(nl padded_line_numbers | sort -k 2,2) \
    <(nl -w 12 -n rz data) |
    sort -k 2,2n |
    cut -d ' ' -f 3-

Где мы нумеруем файл padded_line_numbers, сортируем результат в алфавитном порядке по его второму полю, соединяем его с пронумерованным файлом dataи численно сортируем результат по исходному порядку сортировки padded_line_numbers.

Подстановка процессов здесь используется для удобства. Если вы не можете или не хотите полагаться на него и, скорее всего, не хотите тратить память, необходимую для создания обычных файлов для хранения промежуточных результатов, вы можете использовать именованные каналы :

.

mkfifo padded_line_numbers
mkfifo numbered_data

while read rownum; do
    printf '%.12d\n' "$rownum"
done padded_line_numbers &

nl -w 12 -n rz data >numbered_data &

join -1 2 -2 1 padded_line_numbers numbered_data | sort -k 2,2n | cut -d ' ' -f 3-

Сравнительный анализ

Поскольку особенностью вашего вопроса является количество строк в вашем dataфайле, я подумал, что было бы полезно протестировать альтернативные подходы с сопоставимым объемом данных.

Для тестов я использовал файл данных размером 3,2 миллиарда строк. Каждая строка представляет собой всего 2 байта мусора, поступающего из openssl enc, шестнадцатеричный -, закодированный с помощью od -An -tx1 -w2и с удаленными пробелами с помощью tr -d ' ':

.

$ head -n 3 data
c15d
061d
5787

$ wc -l data
3221254963 data

Файл line_numbersбыл создан путем случайного выбора 10 000 чисел от 1 до 3 221 254 963 без повторений с использованием shufиз GNU Coreutils:

shuf -i 1-"$(wc -l line_numbers

Средой тестирования был ноутбук с четырехъядерным -процессором i7 -2670QM Intel, 16 ГиБ памяти, хранилищем SSD, GNU/Linux, bash5.0 и инструментами GNU.
Единственным измерением, которое я измерил, было время выполнения с помощью встроенной оболочки time.

Вот думаю:

perlкажется, самый быстрый:

$ time perl_script line_numbers data | wc -l
10000

real    14m51.597s
user    14m41.878s
sys     0m9.299s

awkпроизводительность выглядит сопоставимой:

$ time awk 'FNR==NR { seen[$0]++ }; FNR!=NR && FNR in seen' line_numbers data | wc -l
10000

real    29m3.808s
user    28m52.616s
sys     0m10.709s

join, тожекажется сопоставимым:

$ time join <(sort padded_line_numbers) <(nl -w 12 -n rz data) | wc -l
10000

real    28m24.053s
user    27m52.857s
sys     0m28.958s

Обратите внимание, что отсортированная версия, упомянутая выше, почти не имеет снижения производительности по сравнению с этой.

Наконец, sedкажется значительно медленнее :Я убил его примерно через девять часов:

$ time sed -nf <(sed 's/$/p/' line_numbers) data | wc -l
^C

real    551m12.747s
user    550m53.390s
sys     0m15.624s

0
30.06.2020, 19:27
1 ответ

TCP реализован независимо от уровня канала передачи данных. Таким образом, пакет TCP может охватывать один или несколько кадров Ethernet.

Если вы хотите отфильтровать на уровне канала передачи данных, а также проверить более высокие уровни сетевой связи, вам потребуется собрать связь TCP вручную из составных кадров канала данных, а затем проверить информацию уровня 3.

Кадры Ethernet имеют стандартные размеры, поэтому сборка пакетов из фреймов не должна быть такой сложной, и вы можете обнаружить, что большинство шагов квитирования TCP сами по себе могут поместиться в один фрейм Ethernet, но если вы работаете с носителем 802.11 это может стать гораздо более сложной задачей, поскольку уровень 2 может быть зашифрован между клиентами Wi-Fi и точками доступа.

2
18.03.2021, 23:23

Теги

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