As far as I understand, data is transmitted via TCP as a continuous stream, until the connection is terminated. If you look at the structure of the TCP segment, there is even no information about the length of the data (as opposed to UDP, for example). Thus, if we read something from the TCP socket to the buffer, the reading will continue until the connection is closed or the buffer is not full.
However, if you look at the real code, it is not so - recv () on the server reads exactly as many bytes as sent from the client using send ()
How does recv () understand that all data is received and control needs to be returned to the calling code?
Full and minimal example on bare sockets:
Server:
#include <iostream> #include <sys/socket.h> #include <unistd.h> #include <netinet/in.h> #include <memory> #include <arpa/inet.h> const int BUFFER_SIZE = 1024; const int PORT = 12345; int main() { //create server socket int socketFd = ::socket(AF_INET, SOCK_STREAM, 0); if (socketFd < 0) { return -1; } int opt_val = 1; setsockopt(socketFd, SOL_SOCKET, SO_REUSEADDR, &opt_val, sizeof opt_val); //bind to address sockaddr_in socketAddress; socketAddress.sin_family = AF_INET; socketAddress.sin_port = htons(PORT); socketAddress.sin_addr.s_addr = htons(INADDR_ANY); int rc = ::bind(socketFd, reinterpret_cast<sockaddr*>(&socketAddress), sizeof(socketAddress)); if (rc < 0) { return -2; } //listen rc = ::listen(socketFd, SOMAXCONN); if (rc < 0) { return -3; } //accept new connection sockaddr_in socketAdress; unsigned int sizeOfSocketAdress = sizeof(socketAdress); int clientSocket = ::accept(socketFd, (struct sockaddr *)&socketAdress, &sizeOfSocketAdress); if (clientSocket < 0) { return -4; } //receive char buffer[BUFFER_SIZE]; int receivedBytes = ::recv(clientSocket, buffer, BUFFER_SIZE, MSG_NOSIGNAL); std::cout << "Received " << receivedBytes << " bytes : " << buffer << std::endl; // Прочитано 5 байт "hello", хотя буфер не заполнен и соединение не прервано return 0; } Customer:
#include <iostream> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> int main() { struct sockaddr_in sa; int res; int socketFd; socketFd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (socketFd == -1) { perror("cannot create socket"); exit(EXIT_FAILURE); } memset(&sa, 0, sizeof sa); sa.sin_family = AF_INET; sa.sin_port = htons(12345); res = inet_pton(AF_INET, "127.0.0.1", &sa.sin_addr); if (connect(socketFd, (struct sockaddr *)&sa, sizeof sa) == -1) { perror("connect failed"); close(socketFd); exit(EXIT_FAILURE); } auto buf = "hello"; auto len = 5; int sentBytes = ::send(socketFd, buf, len, 0); std::cout << "sent " << sentBytes << "bytes: " << buf << std::endl; std::string tmp; std::getline(std::cin, tmp); //приостановка выполнения, соединение все еще не закрыто return EXIT_SUCCESS; }