Итак, я провожу некоторые тесты TCP для изучения влияния количества данных, передаваемых за соединение, на результирующую пропускную способность. Поэтому я написал сервер и клиент в C, чтобы измерить то, что мне нужно. Затем я использовал сценарий Python для многократного запуска экспериментов (чтобы получить точность +/- 1%, я запускал свой тест в течение 100 с. Для каждой точки данных я проводил эксперимент 33 раза, чтобы получить приличное среднее значение.) с разными входами и для сбора результатов.
Результаты, которые я получаю, кажутся правильными (я могу даже наблюдать ожидаемое плато при больших объемах данных, передаваемых по соединению), за исключением того, что пропускная способность составляет всего 10 % от того, что должно быть ...
Поскольку у меня есть доступ только к одному компьютеру для запуска этого теста, я выполняю тесты на локальном хосте, но это не должно быть проблемой.
Вот мои результаты:
Как видите, лучшая пропускная способность, которую я могу получить, составляет чуть более 300 МБ / с ... Но если я запустить тест пропускной способности с помощью iperf (я удостоверился, что использовал тот же размер окна TCP), на локальном хосте я получил пропускную способность около 3 ГБ / с.
Вот код моего клиента:
int main(int argc, char const *argv[])
{
unsigned int size;
unsigned int timeout;
int sockfd;
struct sockaddr_in server_addr;
if(argc < 4 || argc > 5 ){
usage();
exit(1);
}
const char * ip = "127.0.0.1";
ip = argv[3];
int port = PORT;
if(argc == 5) {
port = atoi(argv[4]);
}
size = atoi(argv[1]);
timeout = atoi(argv[2]);
unsigned int count = 0;
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC_RAW, &start);
clock_gettime(CLOCK_MONOTONIC_RAW, &end);
while((end.tv_sec - start.tv_sec) < timeout) {
// socket create and varification
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
perror("Could not create socket\n");
exit(0);
}
bzero(&server_addr, sizeof(server_addr));
// assign IP, PORT of the server
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(ip);
server_addr.sin_port = htons(port);
// connect the client socket to server socket
if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) != 0) {
perror("connection with the server failed");
exit(1);
}
unsigned int nread = 0;
unsigned int nreadcum = 0;
char* buf = malloc(size);
char* bufbuf = buf;
while(nreadcum < size){
nread = read(sockfd, bufbuf, size-nreadcum);
nreadcum += nread;
bufbuf+=nread;
}
// close connection
close(sockfd);
count++;
clock_gettime(CLOCK_MONOTONIC_RAW, &end);
free(buf);
}
uint64_t sec = (end.tv_sec - start.tv_sec);
double bandwidth = (count*size)/sec;
printf("%u,%lf,%u,%lu\n", size, bandwidth, count, sec);
return 0;
}
А вот код моего сервера:
* 101 8 *
В основном мой код выполняет следующие действия:
- для сервера: дождитесь подключения клиента, отправьте фиктивную полезную нагрузку требуемого размера и закройте соединение с этим клиентом, повторите .
- для клиента: откройте соединение с сервером, прочитайте то, что отправляет сервер, пока сервер не закроет соединение, повторите до тех пор, пока не будет достигнуто установленное время ожидания.
Для расчета пропускную способность, я могу просто сделать (number_of_connections_completed * size_transferred_by_connection) / duration_of_all_transfers
. Я использую python для расчета пропускной способности, чтобы избежать переполнения в C.
TLDR: Пропускная способность, которую я получаю с моими C программами, в 10 раз меньше, чем что это должно быть на localhost. Что может быть источником этой проблемы?