'C Sockets to Measure Bandwidth

As a networking exercise I am trying to write primitive version of iPerf to measure bandwidth over a network using C TCP Sockets. I have set up socket code to establish a connection between a client and a server, and to take as input the amount of time to send data from the client to the server. I understand how this code should work at a high level, but am having trouble implementing it in C++, specifically with figuring out how to send data over the socket for a set time interval before ending the connection. I want the client to open a connection to the server, send data for the user specified time interval, and then when this time interval is up I want it to send the server a flag to let it know that data is done being sent, wait for the server to acknowledge this flag, then calculate the bandwidth during that exchange and exit. I want the server to wait for the client to open a connection, receive data until noticing a flag to denote the end of data, send the client an acknowledgement that it received the flag, then calculate the bandwidth and exit. Here is the rough pseudo-code I have for client/server:

Client:

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

Server:

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); 

I have the working code to set up the sockets but am confused when it comes to implementing the send/receive functionality in C++, and how to keep track of time interval on both server and client. I'm not sure if I should be looking at a timer class in C++, or if there is a way to set up the socket to send data for a set amount of time, etc. Any push in the right direction would be appreciated!



Solution 1:[1]

The first thing you need is a function that will return the current time, with granularity sufficient for your measuring needs. If you had that, then your send loop could look something like this:

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

So the next question is how to implement myClockFunction(). In newer versions of C++, I believe std::chrono has some functions you could use; or if you prefer you could use a POSIX call like times(), or some other OS-specific clock API (depending on which OS you are using).

As for the receiving side, your receiving code will need to know when it has received all of the data -- but if your finish-flag is only one byte long, and your receiver is always waiting to receive a block of 256 bytes, then you've got a problem -- your sender will send the finish-flag, and your receiver will receive it, but will keep on waiting for the other 255 bytes and thus will never send back any response. The easiest solution there would be to make the finish-flag 256 bytes long also; then the receiver could just work as it does now, except that after receiving each 256-byte buffer it would check the contents of the buffer to see if this buffer represents the finish-flag or just normal test data. Alternatively you could have the receiver read only one byte at a time instead of 256, but that would be a bit less efficient since it would then have to call recv() 256 times more often.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jeremy Friesner