[Network] socket programming - TCP (the most complete in history)

Table of contents

1. Initial TCP

1. Characteristics of TCP protocol

2. TCP header:

 3. Confirmation response mechanism

4. Timeout retransmission mechanism

5. Flow control

6. Congestion control

(1) TCP congestion control method

slow start

congestion avoidance

fast retransmission

fast recovery

Second, establish a connection - three-way handshake

 3. Disconnect - wave four times

Four, socket programming

##Client API function

##Server API function


1. Initial TCP

1. Characteristics of TCP protocol

(1) TCP Yes 面向连接的运输层协议. Before using the TCP protocol, the application must first establish a TCP connection. After the data is transferred, the established TCP connection must be released

(2) Each TCP connection can only have two端点 , and each TCP connection can only be 点对点one (one-to-one)

(3) TCP provides 可靠交付(confirmation mechanism, congestion control, flow control, and timeout retransmission services. The data transmitted through the TCP connection is error-free, not lost, not repeated, and arrives in order

(4) Provided by TCP 全双工通信. TCP allows application processes on both sides of the communication to send data at any time. Both ends of the TCP connection are equipped with sending buffer and receiving buffer, which are used to temporarily store the data of two-way communication

(5)面向字节流. "Stream" in TCP refers to流入到进程或从进程流出的字节序列

2. TCP header:

 3. Confirmation response mechanism

The confirmation response mechanism is one of the cores of TCP reliability

The receiver replies with an acknowledgment message (ACK), indicating that it has been received

For example: You ask your friends to hang out together, the confirmation response mechanism in TCP is as follows. Number the sent request, and respond to the corresponding number when responding, so as to ensure the reliability of data transmission.

4. Timeout retransmission mechanism

Timeout retransmission is also one of the necessary conditions for TCP reliability guarantee

Acknowledgment is an ideal situation, but data may be lost during transmission

Let's use the above example of asking friends to play: A sends a message to B, are you at home? After waiting for a long time, A has not received the message from B. At this time, there are the following situations:
(1) B does not want to reply to A's message

TCP holds a "pessimistic attitude". When a packet loss is retransmitted, TCP feels that the subsequent retransmissions are useless with a high probability, so it takes a longer time interval to save bandwidth.

(2) B did not receive the message from A (packet loss: the sent request was lost)
(3) B replied to the message, but A did not receive it (packet loss: the ACK of the response was lost, retransmission means that the same data was received )

(2)(3) Situation: There are two situations of packet loss, and it is impossible for the sender to determine which situation it is. Therefore, unified processing is performed: when a piece of data is sent, a timer will be automatically started inside TCP. If no ACK is received within a certain period of time, the timer will automatically trigger the action of retransmitting the message——retransmitting after timeout

5. Flow control

Flow control: Let the sender's sending rate not be too fast, and let the receiver have time to receive

Using the sliding window mechanism can easily realize the flow control of the sender on the TCP connection. The essence is that when TCP sends data, it puts the data in the sending buffer and puts the received data in the receiving buffer. What the flow control needs to do is to control the sending of the sending end through the size of the receiving buffer. If the receiving buffer of the other party is full, it cannot continue sending. In order to control the rate of the sending end, the receiving end will carry its own window (rwnd) size when performing ACK confirmation, and will inform the sending end of the size of its own buffer, and perform corresponding flow control.

6. Congestion control

拥塞控制That is 防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载. All congestion control needs to do is a premise, that is,网络能够承受现有的网络负荷

(1) TCP congestion control method

There are four algorithms for TCP congestion control, namely 慢开始(slow-start), 拥塞避免(congestion avoidance), 快重传(fast retransmit) and 快恢复(fast recovery)

slow start

When the host starts to send data, because it does not know the load of the network, if a large number of data bytes are injected into the network immediately, it may cause network congestion. Experience has shown that it is better to probe first, that is 由小到大逐渐增大发送窗口, that is,由小到大逐渐增大拥塞窗口数值。

When executing the slow start algorithm, each time the sender receives an acknowledgment ACK for a new segment, it adds 1 to the congestion window value, and then starts the next round of transmission. Therefore, the congestion window cwnd grows exponentially with the number of transmission rounds. When the congestion window cwnd grows to the slow start threshold ssthresh, the congestion avoidance algorithm is changed to execute, and the congestion window grows linearly

ssthresh: slow start threshold, generally there will be an initial value

congestion avoidance

Let the congestion window cwnd increase slowly, that is, increase the sender's congestion window cwnd by 1 every time a round-trip time RTT passes, instead of doubling it as in the slow start phase. The congestion window cwnd  按线性规律缓慢增长grows much more slowly than the congestion window of the slow-start algorithm

"Congestion avoidance" is not completely able to avoid congestion, but controls the congestion window to grow linearly,使网络比较不容易出现拥塞

fast retransmission

Using the fast retransmission algorithm can make the sender 尽早知道发生了个别报文段的丢失. The fast retransmission algorithm first requires the receiver not to wait for the piggyback acknowledgment when it sends the data, but to send a duplicate acknowledgment of the received segment immediately even if 立即发送确认it is received失序的报文段

fast recovery

The sender knows that only individual segments are currently lost. So instead of starting the slow start, 快恢复the algorithm is executed. At this time, the sender adjusts the threshold ssthresh = cwnd / 2, sets the congestion window cwnd = ssthresh at the same time, and starts to execute the congestion avoidance algorithm

Second, establish a connection - three-way handshake

There are three steps to establish a TCP connection, namely three-way handshake

Let me give you a simple example first. We can compare it to making a phone call, as follows:

 

The first time A does not know whether B can hear his own voice, A says to B "Hey, can you hear it?" It is B's reply to A, "I can hear it, how about you", and the third reply from A confirms that both parties can hear the voice, that is, A's reply to B, "I can too", and the call can be guaranteed by the last three times Normal, similar to the three-way handshake when the network establishes a connection.

Is it okay to shake hands twice? ?
No,
the two-way handshake can only ensure that the one-way connection is unobstructed. The TCP protocol is two-way. The third handshake is to let the server know that the client has agreed to the connection request. The two handshakes can only confirm that the network from the client to the server is reachable, but cannot guarantee that the network from the server to the client is reachable. So we must ensure two-way reachability.

 As shown in the figure above, if there is no third handshake, it is not known whether A’s receiver is normal, resulting in a normal call

TCP three-way handshake:

First handshake:

The TCP client intends to establish a connection and sends a connection request message to the server. The client requests a connection, and the client performs a synchronous sending state (SYN-SEND). In the connection request message, SYN=1 indicates that this is a request connection In the message, the serial number field seq=x (x is an initial value) is used as the initial serial number of the client

Second handshake:

After receiving the client's request, the TCP server will send a confirmation request message to the client if it is connected, and the server enters the synchronous receiving state. In the confirmation message, the synchronization bit SYN and the confirmation bit ACK are set to 1. Indicates that this is a request confirmation message. Set the serial number seq to an initial value y as the initial serial number of the server. Use the confirmation field ack=x+1 as confirmation to the client

The third handshake:

After receiving the confirmation signal from the server, the TCP client will also send a confirmation message to the server, enter the connection established (ESTABLISHED), and send a confirmation message for server confirmation.

Acknowledgment bit ACK=1, indicating that this is an acknowledgment message

The serial number seq=x+1, means x is sent for the first time, and x+1 is sent for the second time

The confirmation number ack=y+1 is the confirmation of the server

After the server receives it, the incoming connection has been established

 3. Disconnect - wave four times

   There are four steps to disconnect the TCP connection, that is, wave four times

First wave:

The TCP client actively closes the TCP connection, the TCP client sends a connection release (disconnect) message to the server, and enters the termination waiting state 1,

In the disconnection release message:

(1) The termination bit FIN and the confirmation bit ACK should be set to 1, indicating that it is a TCP connection release message, and confirm the previous message at the same time

(2) The serial number seq is set to u (representing a specific value), which is equal to the last byte of the data that has been transmitted before + 1

(3) The confirmation number ack is set to v, which is equal to the last byte sequence number of the previously received data + 1

Second wave:

When the TCP server receives the TCP connection disconnection request message, it will send a confirmation message to the client and enter the shutdown waiting state. After receiving the confirmation, the client will enter the termination waiting state 2

In a disconnect confirmation message:

  1. Confirmation number ACK=1, which means it is a confirmation message
  2. The serial number seq=v, which is equal to the last byte sent by the server + 1, matches the confirmation number of the next waved client

Continue to complete the transmission of the data that is not currently transmitted

Third wave:

The TCP server sends a connection release message to the client and enters the final confirmation state

In the server connection release message:

  1. The termination bit FIN and the confirmation bit ACK are set to 1, indicating that this is a TCP connection release, and at the same time confirm the previous data
  2. Serial number seq=w, at this time the server is in a half-closed state (disconnection is bidirectional)
  3. Confirmation number ack=u+1, repeated confirmation of release

Fourth wave:

After receiving the connection release from the server, the TCP client sends a confirmation message and enters the time waiting state

Acknowledgment bit ACK=1, indicating that it is an acknowledgment message

Sequence number seq=u+1 (the last time was u, send it again), indicating that it is a release message

The confirmation number ack=w+1 means it is a confirmation

 Why does TCP wait for 2MSL after waving four times?

An MSL indicates the maximum time for a message to survive. Whether it is a message sent by A to B or a message sent by B to A, it can survive up to 1MSL, so wait for 2MSL, that is, the message comes and goes.

Four, socket programming

Client: analogous to making a phone call

analogy

Function

function

have mobile phone

Create a socket (with a corresponding TCP protocol)

socket()

have a mobile number

Bind socket (with its own network information)

bind()

Dial the other party's phone number

Request a server connection (establish a connection with the server)

connect()

make a call

send and receive data (communicate)

read()、write()、recv()、send()、

hang up the phone

End communication (close socket)

close()

##Client API function

1. Create a socket

#include <sys/types.h>

#include <sys/socket.h>

//Create a socket file, add a corresponding network communication protocol (file) to the process, and the return value is the file descriptor of the creation number (socket descriptor represents a set of protocols---sockets)

int socket(int domain, int type, int protocol);

Parameter 1:

int domain:地址族,选用那种网络层协议地址

AF_INET------IPV4
AF_INET6-----IPV6

Parameter 2:

int type:套接字类型

SOCK_STREAM--------TCP

SOCK_DGRAM---------UDP

SOCK_RAW:原始套接字(没有传输层协议)

Parameter 3:

int protocol:套接字协议

 0:套接字默认协议

return value:

int:整数---------文件描述符(套接字文件)

成功:返回套接字描述符 >= 0

失败:返回-1

2. Bind the socket

#include <sys/types.h> /* See NOTES */

#include <sys/socket.h>

//Bind the local network information to the socket

int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

Parameter 1:

int sockfd:绑定本地网络信息到哪个套接字上(绑定到哪一套协议上)

Parameter 2:

const struct sockaddr *addr:结构体地址,这个结构体中存储的本地网络信息(要绑定的网络信息ip、port)

struct sockaddr {//通用结构体,表示一个网络信息内容

    sa_family_t sa_family;

    char sa_data[14];

}

//IPV4 网络信息结构体

struct sockaddr_in {

    sa_family_t sin_family;//地址族 AF_INET

    in_port_t sin_port;//端口

    struct in_addr sin_addr;//结构体变量--ip地址

};


/* Internet address. */

struct in_addr {

      uint32_t s_addr;//ipv4地址

};

Parameter 3:

socklen_t addrlen:整数,结构体大小(确定信息结构体的大小)

return value:

成功:返回0

失败:返回-1

3. Request connection

#include <sys/types.h>          

#include <sys/socket.h>

// Request to establish a connection with the server

int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

Parameter 1:

int sockfd:客户端的套接字,使用套接字与服务端建立连接

Parameter 2:

const struct sockaddr *addr:服务端的ip、prot信息,客户端要和哪个服务器建立连接

Parameter 3:

socklen_t addrlen:结构体的大小

return value:

成功:返回0
失败:返回-1

Implementation code:

//TCP客户端进行通信(先发再收)
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
 #include <netinet/in.h>
#include <sys/types.h>         
#include <sys/socket.h>
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{

	//1、创建套接字,选择对应的网络通信协议组
	int socketfd = socket(AF_INET,SOCK_STREAM,0);//选择TCP协议
		if(socketfd < 0)
		{
			printf("socket create error\n");
			return -1;
		}
		

	//2、绑定套接字,对套接字添加自己当前进行需要到本地网络信息

	struct sockaddr_in clientaddr;//有一个IPV4网络信息结构体
	clientaddr.sin_family  = AF_INET;//地址族-----IPV4
	clientaddr.sin_port = htons(20000);//为当前进程添加的端口号为10000
	clientaddr.sin_addr.s_addr = inet_addr("0.0.0.0");

	bind(socketfd,(struct sockaddr *)&clientaddr,sizeof(clientaddr));
	//与服务器建立连接
	struct sockaddr_in serveraddr;//服务端IPV4网络信息结构体
	serveraddr.sin_family  = AF_INET;//地址族-----IPV4
	serveraddr.sin_port = htons(10000);//为当前进程添加的端口号为10000
	serveraddr.sin_addr.s_addr = inet_addr("192.168.138.1");
	if(connect(socketfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr))<0)
	{
		printf("connect error\n");
	}else{
		printf("connect ok\n");
	}
	
	char buf[20];
	while(1)
	{
		memset(buf,0,20);//清空buf
   		fgets(buf,20,stdin);
		write(socketfd,buf,20);//发送

		memset(buf,0,20);
		read(socketfd,buf,20);//接收
		printf("data is %s\n",buf);
	}
	close(socketfd);
	return 0;
}

Server: analogy to answering the phone

analogy

Function

function

have mobile phone

Create a socket (with a corresponding TCP protocol)

socket()

have a mobile number

Bind socket (with its own network information)

bind()

Waiting for a call (Standby)

Listen to the server socket (check if there is a client connection)

listen()

answer the phone

Receive the connection request from the agreed client

accept()

make a call

send and receive data (communicate)

read()、write()、recv()、send()、

hang up the phone

End communication (close socket)

close()

##Server API function

1. Create a socket

#include <sys/types.h>

#include <sys/socket.h>

//Create a socket file, add a corresponding network communication protocol (file) to the process, and the return value is the file descriptor of the creation number (socket descriptor represents a set of protocols---sockets)

int socket(int domain, int type, int protocol);

Parameter 1:

int domain:地址族,选用那种网络层协议地址
AF_INET------IPV4
AF_INET6------IPV6

Parameter 2:

int type:套接字类型

SOCK_STREAM--------TCP

SOCK_DGRAM---------UDP

SOCK_RAW:原始套接字(没有传输层协议)

Parameter 3:

int protocol:套接字协议

 0:套接字默认协议

return value:

int:整数---------文件描述符(套接字文件)

成功:返回套接字描述符 >= 0

失败:返回-1

2. Binding socket

#include <sys/types.h> /* See NOTES */

#include <sys/socket.h>

//Bind the local network information to the socket

int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

Parameter 1:

int sockfd:绑定本地网络信息到哪个套接字上(绑定到哪一套协议上)

Parameter 2:

const struct sockaddr *addr:结构体地址,这个结构体中存储的本地网络信息(要绑定的网络信息ip、port)

struct sockaddr {//通用结构体,表示一个网络信息内容

sa_family_t sa_family;

char sa_data[14];

}

//IPV4 网络信息结构体

struct sockaddr_in {

sa_family_t sin_family;//地址族 AF_INET

in_port_t sin_port;//端口

struct in_addr sin_addr;//结构体变量--ip地址

};



/* Internet address. */

struct in_addr {

  uint32_t s_addr;//ipv4地址

};

Parameter 3:

socklen_t addrlen:整数,结构体大小(确定信息结构体的大小)

return value:

成功:返回0

失败:返回-1

3. Monitor

#include <sys/types.h>          

 #include <sys/socket.h>

Listening and waiting for client connection, if there is a client connection, it will only store the client connection (a listening queue will be created), as long as there is a client to connect, it will be placed in the listening waiting queue - you can always view the server's own information, whether there is a client connection. And then the socket can only be used for listening, not for communicating with the client

       int listen(int sockfd, int backlog); automatically listen after calling (check if there is a client connection)

Parameter 1:

int sockfd:要进行监听的套接字,就是之前绑定了服务器ip、port的套接字,
            表示要监听哪个套接字是否有客户端连接

Parameter 2:

int backlog:最多同时能够存储多少个客户端连接——等待队列大小

return value:

成功——  0     

失败——-1

4. Agree to the connection request

#include <sys/types.h>          /* See NOTES */

#include <sys/socket.h>

//The server agrees to the connection request (take out a client connection request from the waiting queue and establish a connection. If there is no connection request in the listening queue, it will block and wait for the listening queue to have a connection request) - must receive a connection request

       int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

Parameter 1:

int sockfd:监听套接字,从哪个监听中取出连接

Parameter 2:

struct sockaddr *addr:用于存储客户端ip,port,不需要写NULL

Parameter 3:

socklen_t *addrlen:结构体大小

return value:

成功——返回与连接成功的客户端通信的套接字   

失败——-1

5. Send or receive data

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

ssize_t recv(int sockfd, void *buf, size_t len, int flags);

Parameter 1:

int sockfd:套接字

Parameter 2:

const void *buf:要发送或接收的数据

Parameter 3:

size_t len:数据大小

Parameter 4:

int flags:标志,选项

0:阻塞

Implementation code:

//tcp服务端,与客户端进行通信
#include <sys/types.h>     
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
	//1、创建套接字
	int sockfd = socket(AF_INET,SOCK_STREAM,0);//在服务器创建TCP套接字
	
	//2、绑定套接字
	struct sockaddr_in serveraddr;
	serveraddr.sin_addr.s_addr = inet_addr("192.168.124.80");
	serveraddr.sin_port = htons(9999);
	serveraddr.sin_family = AF_INET;

	bind(sockfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));

	//3、监听套接字
	listen(sockfd,10);
	
	//4、接受客户端连接
	int clientfd = accept(sockfd,NULL,NULL);//返回值就是与客户端通信的套接字
	printf("ok\n");	

	//服务器与客户端如何进行通信
	char buf[50];
	while(1)
	{
		printf("recv\n");
		sleep(10);
		memset(buf,0,50);
		int num = recv(clientfd,buf,50,0);//返回值就是接收的大小
		if(strcmp(buf,"quit\n") == 0)
			break;
		printf("size is %d; data is %s",num,buf);
		send(clientfd,buf,50,0);
		printf("send ok\n");
	}
	close(clientfd);

	close(sockfd);

	return 0;
}

Guess you like

Origin blog.csdn.net/qq_53676406/article/details/129502560