null

Передача файлов через netcat

Эта статья не несёт в себе огромного прикладного смыла, хотя в некоторых случаях быстрая передача файлов через netcat может выручить. Основная её цель – объяснить, почему работает именно так и как сделать, чтобы работало быстрее. Итак, было замечено, что скорость передачи файлов по ftp составляет ~8 Mb/s, а через netcat ~1MB/s. Экперимент проводился в 100BaseTX сети, состоящей из двух узлов (Freebsd и Solaris).

На одном узле включаем сервер (Solaris):

# nc -l -p 1234 > /tmp/ccc

На другом запускаем копирование (FreeBSD):

# dd if=/tmp/file | nc 192.168.1.1 1234

Будем смотреть количество переданных пакетов (Solaris):

# snoop -o /tmp/snoop -d dmfe1 port 1234

Смотрим результат:

48183818 bytes transferred in 24.023524 secs (2005693 bytes/sec)

Количество переданных пакетов пакетов 23423. При копировании по ftp пакетов передаётся около 5000. Очевидно, что данные по ftp передаются бОльшими порция, поэтому и быстрее. Смотрим на системные вызовы ftp-клиента:

# truss -p 1501

….

read(4," 87\n04:02:35 3 "...,32768) = 32768 (0x8000)

write(5," 87\n04:02:35 3 "...,32768) = 32768 (0x8000)

….

4 - дескриптор файла /tmp/file, 5 – дескриптор сокета. Читаем и пишем кусками по 32768 байт.

Смотрим на системные вызовы nc-клиента:

# truss -p 1311

….

read(0," 4 11 0 86\n04"...,1024) = 1024 (0x400)

write(3," 4 11 0 86\n04"...,1024) = 1024 (0x400)

….

В этом случае мы читаем и пишем кусками по 1024 байт, поэтому узкое место в количесте прерываний в секунду (смотрим vmstat 1 на Solaris'е и видим, что их число может доходить до 5000!!!). Задача ясна – нужно увеличить буфер на отправку и на приём.

Берём netcat: http://internap.dl.sourceforge.net/sourceforge/netcat/netcat-0.7.1.tar.gz

В файле src/core.c видим, что размер буфера зашит в коде в двух местах:

int core_readwrite(nc_sock_t *nc_main, nc_sock_t *nc_slave)

{

int fd_stdin, fd_stdout, fd_sock, fd_max;

int read_ret, write_ret;

unsigned char buf[1024];

bool inloop = TRUE;

fd_set ins, outs;

struct timeval delayer;

assert(nc_main && nc_slave);

…..

 

for (socks_loop = 1; socks_loop <= sockbuf[0]; socks_loop++) {

int recv_ret, write_ret;

struct msghdr my_hdr;

unsigned char buf[1024];

struct iovec my_hdr_vec;

struct sockaddr_in rem_addr;

 

Исправляем на 32768 на обоих хостах, компилируем, запускаем копирование, получаем ~9000 Kb/s. А если увеличить буфер до 65536 байт, то скорость возрастает до 10500 Kb/s.

О себе

В компании TUNE IT я занимаю должность инженера. В сферу моих профессиональных интересов входят следующие направления:

  • Администрирование UNIX систем (Solaris, Freebsd);
  • Обслуживание серверов и систем хранения данных фирмы Sun Microsystems;
  • Обеспечение безопасности вычислительных систем и сетей;
  • Виртуализация вычислительных инфраструктур.

Ничего не найдено. n is 0