2017-01-10 10 views
0

В качестве сетевого упражнения я пытаюсь написать примитивную версию iPerf для измерения полосы пропускания по сети с использованием C TCP Sockets. Я установил код сокета, чтобы установить соединение между клиентом и сервером, и принять в качестве входных данных количество времени для отправки данных от клиента на сервер. Я понимаю, как этот код должен работать на высоком уровне, но у меня возникли проблемы с его реализацией на C++, в частности, с целью выяснить, как отправлять данные по сокету за заданный интервал времени до окончания соединения. Я хочу, чтобы клиент открыл соединение с сервером, отправил данные для указанного пользователем интервала времени, а затем, когда этот временной интервал закончился, я хочу, чтобы он отправил серверу флаг, чтобы сообщить ему, что данные отправляются, ждать чтобы сервер подтвердил этот флаг, затем вычислить полосу пропускания во время этого обмена и выйти. Я хочу, чтобы сервер дождался, пока клиент откроет соединение, получит данные, не заметив флаг для обозначения конца данных, отправьте клиенту подтверждение, что он получил флаг, а затем вычислить пропускную способность и выйти. Вот грубый псевдокод я для клиента/сервера:C Сокеты для измерения полосы пропускания

Клиент:

time = userinput(); 
host = userinput(); 
port = userinput(); 

sockaddr_in address; // set host and port of this 

s = socket(AF_INET, SOCK_STREAM, 0); // create TCP socket 
connect(s, &address, sizeof(address)); // connect to the user input address 


char data[256]; // initialize to all 0's 
char finish_flag = 'F'; // send flag to signify data is done being sent 
char ack; // buffer to store server's response to the finished_flag 
int bytes_sent = 0; // counter for how much data is sent 

while (time_interval) { 
    send(s, data, 256, 0); 
    bytes_sent += 256; 
} 

send(s, &finished_flag, 1, 0); // let the server know data is done being sent 

recv(s, &ack, 1, MSG_WAITALL); // wait for the server's acknowledgement 

bandwidth = (bytes_sent/time_interval); // use actual time socket was open for, not user input time 

Сервер:

port = userinput(); 


sockaddr_in address; // set host and port of this 

s = socket(AF_INET, SOCK_STREAM, 0); // create TCP socket 
listen(s, 1); // listen for 1 connection, the client 
int sock = accept(s, &address, sizeof(address)); // accept connection from the client 

char data[256]; // buffer to receive data in 
char finish_flag = 'F'; // flag to look for 
char ack; // ack flag to send back to client 
int bytes_rec = 0; // counter for how much data is received 

while (no finish_flag received) { 
    recv(sock, &data, 256, MSG_WAITALL); 
    bytes_rec += 256; 
    // keep track of time interval somehow 
} 

send(sock, &ack, 1, 0); 

bandwidth = (bytes_rec/time_interval); 

У меня есть рабочий код для настройки сокетов, но я смущен, когда он приходит к реализации функций отправки/получения на C++ и как отслеживать временной интервал как на сервере, так и на клиенте. Я не уверен, должен ли я смотреть на класс таймера на C++, или если есть способ настроить сокет для отправки данных за определенное количество времени и т. Д. Любое нажатие в правильном направлении было бы оценено!

ответ

0

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

long nowMilliSeconds = myClockFunction(); 
long sendUntilThisTime = nowMilliseconds + (5*1000); // stop sending after 5 seconds 
while(myClockFunction() < sendUntilThisTime) 
{ 
    // send some more data! 
} 

Итак, следующий вопрос, как реализовать myClockFunction(). В новых версиях C++ я считаю, что std :: chrono имеет некоторые функции, которые вы могли бы использовать; или, если вы предпочитаете, вы могли бы использовать вызов POSIX, например times(), или какой-либо другой OS-специфический API часов (в зависимости от того, какую ОС вы используете).

Что касается принимающей стороны, то ваш получающий код должен знать, когда он получил все данные, но если ваш финишный флаг имеет длину только один байт, а ваш приемник всегда ждет, чтобы получить блок 256 байт, то у вас есть проблема - отправитель отправит флаг окончания, и ваш получатель получит его, но будет продолжать ждать 255 байт и, таким образом, никогда не отправит ответ. Самое простое решение - сделать также финишный флаг длиной 256 байтов; то приемник мог бы работать так же, как сейчас, за исключением того, что после приема каждого 256-байтового буфера он проверял содержимое буфера, чтобы увидеть, представляет ли этот буфер флаг окончания или только обычные тестовые данные. В качестве альтернативы вы могли бы получать приемник только по одному байту за раз, а не 256, но это было бы немного менее эффективно, так как тогда ему пришлось бы вызывать recv() 256 раз чаще.