meta data for this page
  •  

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
courses:ct30a5000:assignment2notes [2012/10/17 13:29]
julaakko [Comments]
courses:ct30a5000:assignment2notes [2012/11/06 20:42]
julaakko [Comments]
Line 19: Line 19:
 | 0404544 | Ok division of code but using multiple files would make it easier to read.  For possible longer user input it would be good idea to check if fgets() stopped at newline marker (is there anything else in the buffers). The amount of received data is not checked – you should not expect that you always get enough data. Partial receiving is not handled. Nicknames should be separated with NULLs (\0) instead of semicolon. You should set the data buffers to NULLs before sending since it might contain some garbage – this is because you're not padding the nickname with NULLs before putting it into buffer, look up the memset() function. Lots of Valgrind errors. Duplicate nicknames are not checked. Server does not inform clients when quitting. Lots of leaking memory. | | 0404544 | Ok division of code but using multiple files would make it easier to read.  For possible longer user input it would be good idea to check if fgets() stopped at newline marker (is there anything else in the buffers). The amount of received data is not checked – you should not expect that you always get enough data. Partial receiving is not handled. Nicknames should be separated with NULLs (\0) instead of semicolon. You should set the data buffers to NULLs before sending since it might contain some garbage – this is because you're not padding the nickname with NULLs before putting it into buffer, look up the memset() function. Lots of Valgrind errors. Duplicate nicknames are not checked. Server does not inform clients when quitting. Lots of leaking memory. |
 | 0404557 | Lots of implicit declaration errors, see manual pages of those functions and use the headers mentioned there. Ok division of code but usage of more functions will provide flexibility to code. Partial receiving or sending not handled – you should always check how much has been sent or received. Valgrind errors. Nothing really works with multiple clients, only messages from first client reaches the server. Do not expect that clients send data immediately after connecting, after the client is accepted wait for select to tell if the new socket (not the server listening socket) contains data available for reading. Read what you can in one recv() and check if you got a full packet ready to be processed, if not, read the rest when it arrives and process it later – this would require some buffering of data for each client. You should at least initialize all variables, especially buffers, before use.  | | 0404557 | Lots of implicit declaration errors, see manual pages of those functions and use the headers mentioned there. Ok division of code but usage of more functions will provide flexibility to code. Partial receiving or sending not handled – you should always check how much has been sent or received. Valgrind errors. Nothing really works with multiple clients, only messages from first client reaches the server. Do not expect that clients send data immediately after connecting, after the client is accepted wait for select to tell if the new socket (not the server listening socket) contains data available for reading. Read what you can in one recv() and check if you got a full packet ready to be processed, if not, read the rest when it arrives and process it later – this would require some buffering of data for each client. You should at least initialize all variables, especially buffers, before use.  |
 +
 +===== Making sure that all data is sent and received with TCP =====
 +
 +A example when all is sent in one call, e.g. in client ([[http://​beej.us/​guide/​bgnet/​output/​html/​multipage/​advanced.html#​sendall|another one]]):
 +<code c>
 +int write_to_socket(int sockfd, char* data, unsigned int data_len, unsigned int *data_written)
 +{
 +  int wrote = 0;
 +  ​
 +  // Initialize the pointer value to 0
 +  *data_written = 0;
 + 
 +  // While we have something to write
 +  while(*data_written < data_len)
 +  {
 +    // Write remaining data
 +    if((wrote = send(sockfd,&​data[*data_written],​data_len - *data_written,​0)) < 0) return -1;
 +
 +    // Update the written amount for pointer
 +    *data_written += wrote;
 +  }
 +  ​
 +  return 1;
 +}
 +</​code>​
 +
 +
 +For receiving data you have to use a different approach, especially with multiple connections. If the data is not received in one ''​recv''​ call keep reading until the full packet is completely read. One example:
 +<code c>
 +
 +int read_from_socket(int sockfd,​char* buffer, unsigned int total, unsigned int *remaining)
 +{
 +  do
 +  {
 +    // Read 0 or less -> we're done here, return -1 or 0
 +    if((data_read = recv(sockfd,&​buffer[total-*remaining],​*remaining)) < 1) return data_read;
 +  ​
 +    // otherwise update the remaining amount
 +    else *remaining -= data_read;
 +    ​
 +  } while (*remaining > 0)
 +  ​
 +  return 1; //ok
 +
 +</​code>​
 +
 +Just keep in mind that when designing the reading approach for a server it is good way to balance the load by reading only certain amount of data per client and then checking if it is fully received. If not, proceed to the next client and so on.
 +
 +A {{:​courses:​ct30a5000:​tcptest.tar.gz|demonstration server and client}} using ''​MSG_DONTWAIT''​ flag with ''​send''​. Client sends a 1 Mb of data to the server and both quit after the data is sent full / all is received. Compile with ''​make''​ and run the client with <​code>​./​tcptestc <​serverIP>​ <server port></​code>​ and the server with <​code>​./​tcptests <​port></​code>​
 +
 +The ''​MSG_DONTWAIT''​ demonstrates the effect when the send buffer is full and the application cannot write more -> the function returns and in next round attempts to write more into the buffer. Without the flag the ''​send()''​ function **blocks until all requested data is sent** - it will fill the buffer, wait until there is space, fill the remaining space, wait .. and it continues until all is sent.
 +
 +