Once an application successfully establishes a socket connection, it is ready to start transferring data over the connection. With stream (TCP) sockets, data transfer is said to be "reliable," meaning that the application may assume that the underlying transport will ensure that the data gets to the remote host without duplication or corruption. When a connection is established on a stream socket, a the TCP transport creates a "virtual circuit" between the two machines. This circuit remains open until both applications decide that they are done sending data on the circuit (typically a "graceful" close), or until a network error occurs which causes the circuit to be terminated abnormally.
An application sends data using the send() API. This API takes a socket descriptor, a pointer to a buffer to send, the length of the buffer, and an integer which specifies flags which can modify the behavior of send(). To receive data, an application uses the recv() API, which takes a pointer to a buffer to fill with data, the length of the specified buffer, and a flags integer. recv() returns the number of bytes actually received, and send() returns the number of bytes actually sent. Note that applications should always check the return codes of send()and recv() for the number of bytes actually transferred, since it may be different from the number requested. Because of the stream-oriented nature of TCP sockets, there isn't necessarily a one-to-one correspondence between send() and recv() calls. For example, a client application may perform ten calls to send(), each for 100 bytes. The system may combine or "coalesce" these sends into a single network packet, so that if the server application did a recv() with a buffer of 1000 bytes, it would get all the data at once.
Therefore, an application must not make any assumptions about how data will arrive. A server which expects to receive 1000 bytes should call recv()in a loop until it has received all of the data:
SOCKET s; int bytes_received; char buffer[1000]; char *buffer_ptr; int buffer_length; . . buffer_ptr = buffer; buffer_length = sizeof(buffer); /* Receive all outstanding data on socket s */ do { bytes_received = recv(s, buffer_ptr, buffer_length, 0); if (bytes_received == SOCKET_ERROR) { sprintf(buf,"Windows Sockets error %d: Error while receiving data.", WSAGetLastError()); MessageBox (hWnd,buf,"Windows Sockets Error",MB_OK); shutdown_app(); } buffer_ptr += bytes_received; buffer_length -= bytes_received; } while (buffer_length > 0);
Likewise, an application which wants to send 1000 bytes should send() in a loop until all of the data has been sent:
SOCKET s; int bytes_sent; char buffer[1000]; char *buffer_ptr; int buffer_length; buffer_ptr = buffer; buffer_length = sizeof(buffer); /* Enter send loop until all data in buffer is sent */ do { bytes_sent = send(s, buffer_ptr, buffer_length, 0); if (bytes_sent == SOCKET_ERROR) { sprintf(buf,"Windows Sockets error %d: Error while sending data.", WSAGetLastError()); MessageBox (hWnd,buf,"Windows Sockets Error",MB_OK); shutdown_app(); } buffer_ptr += bytes_sent; buffer_length -= bytes_sent; } while (buffer_length > 0);