The problem of TCP viscosity and the borderless _socket of data (sockets)

Source: Internet
Author: User
Tags terminates htons
In the last section we talked about the socket buffer and data transfer process, you can see that the data received and sent is irrelevant, the read ()/recv () function no matter how many times the data sent, will receive as much data as possible. That is, the number of executions of read ()/recv () and write ()/send () may be different.

For example, write ()/send () repeats three times, each time the string "ABC" is sent, the read ()/recv () on the target machine may be received three times, each time receiving "ABC", or it may be received two times, the first time receive "Abcab", the second time receive "CABC Or you may receive the string "ABCABCABC" at once.

Suppose we want the client to send a student's number each time, so that the server to return the student's name, address, results, and so on, there may be problems, the server can not distinguish between the student's school number. For example, the first time to send 1, the second send 3, the server may be treated as 13来, the return of the information is clearly wrong.

This is the "sticky" problem with the data, and multiple packets sent by the client are received as a packet. Also known as the borderless nature of the data, the Read ()/recv () function does not know the start or end sign of the packet (nor does it actually have any start or end flags) and treats it as a continuous stream of data.

The following code illustrates the sticky packet problem where the client sends data to the server three times in a row, and the server receives all the data at once.

Server-side code server.cpp:
#include <stdio.h> #include <windows.h> #pragma comment (lib, "Ws2_32.lib")//Load Ws2_32.dll #define BUF_SIZE 1 int main () {wsadata wsadata; WSAStartup (Makeword (2, 2), &wsadata); Create socket Socket Servsock = socket (af_inet, sock_stream, 0); Binding socket sockaddr_in sockaddr; memset (&sockaddr, 0, sizeof (SOCKADDR)); Each byte is filled with 0 sockaddr.sin_family = pf_inet; Use IPv4 address sockAddr.sin_addr.s_addr = inet_addr ("127.0.0.1"); The specific IP address Sockaddr.sin_port = htons (1234); Port Bind (Servsock, (sockaddr*) &sockaddr, sizeof (SOCKADDR)); Into the Listening state listen (Servsock, 20); Receive client request SOCKADDR CLNTADDR; int nsize = sizeof (SOCKADDR); Char Buffer[buf_size] = {0}; Buffer SOCKET Clntsock = Accept (Servsock, (sockaddr*) &clntaddr, &nsize); Sleep (10000); Note Here, let the program suspend 10 seconds//receive the data from the client, and return the int recvlen = recv (clntsock, buffer, buf_size, 0); Send (clntsock, buffer, Recvlen, 0); Closes the socket and terminates the use of the DLL closesocket (clntsock); Closesocket (Servsock); WSACleanup (); return 0; }
Client code client.cpp:
#include <stdio.h> #include <stdlib.h> #include <WinSock2.h> #include <windows.h> #pragma Comment (lib, "Ws2_32.lib")//load Ws2_32.dll #define BUF_SIZE int main () {//Initialize DLL wsadata wsadata; WSAStartup (Makeword (2, 2), &wsadata); Initiate a request to the server sockaddr_in sockaddr; memset (&sockaddr, 0, sizeof (SOCKADDR)); Each byte is filled with 0 sockaddr.sin_family = pf_inet; SOCKADDR.SIN_ADDR.S_ADDR = inet_addr ("127.0.0.1"); Sockaddr.sin_port = htons (1234); Create socket Socket sock = socket (pf_inet, sock_stream, ipproto_tcp); Connect (sock, (sockaddr*) &sockaddr, sizeof (SOCKADDR)); Get user input string and send to server char bufsend[buf_size] = {0}; printf ("Input A string:"); Gets (Bufsend); for (int i=0; i<3; i++) {Send (sock, Bufsend, strlen (Bufsend), 0);}//Receiving server returns data char bufrecv[buf_size] = {0}; Recv (sock, Bufrecv, buf_size, 0); Output received data printf ("Message form server:%s\n", BUFRECV); Closesocket (sock); Close socket WSACleanup (); Terminates the use of DLL system ("pause"); return 0; }
Run server first, run client again, and enter the string "ABC" in 10 seconds, and then wait a few seconds, and the servers will return the data. The results of the operation are as follows:
Input a STRING:ABC
Message form SERVER:ABCABCABC

The key of this program is the Code sleep (10000) in line 31st of Server.cpp; , which allows the program to suspend execution for 10 seconds. During this time, the client sends the string "ABC" three consecutive times, because the server is blocked, the data can only accumulate in the buffer, 10 seconds later, the server starts to run, reads all the backlog data from the buffer, and returns it to the client.

In addition, the 34th line of client.cpp code should be described. The client executes to the recv () function, which is blocked until 10 seconds after the server returns data, because there is no data in the input buffer. The intuitive effect that the user sees is that the client pauses for a period of time to output the results returned by the server.

The client's send () sends three packets, and the server's recv () receives only one packet, which is a good illustration of the sticky packet problem.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.