Basic TCP socket programming flow

Overview of the basic programming process

To realize the communication between the client and the server, the client and the server need to be completed together. Among them, the programming process of the TCP server and the client is shown in the figure: Insert picture description here
first, the server creates a socket, then bind binds the communication port, and creates a listen queue. After that, the communication process began. At this time, the server is blocked at accept until the tcp client takes the initiative to connect for a three-way handshake to establish a connection. At this time, the write function of the client sends a request to the server, and the server reads to read the request and process it. After the processing is completed, the write function of the server is called to send a response message to the client, and the client receives the response message through read. At this point, the entire data exchange is over, and the client can actively shut down.

Socket programming on the client and server

Insert picture description here
The family is usually AF_INET under the IPV4 protocol, and AF_INET6 under the IPv6 protocol. The type is SOCK_STREAM under the TCP transmission protocol, and SOCK_DGRAM under the UDP protocol. Generally speaking, the parameter protocol of the function socket is set to 0, unless it is used on the original socket

The client connect function establishes a link with the server

The TCP client uses the connect function to establish a connection with the TCP server. Insert picture description here
sockfd is the return value of the socket function. The second parameter is a pointer to the socket address structure, and the third parameter is the size of the structure. Insert picture description here
sin_port is the port number and S_addr is the server network ip address. Through this program, the client can connect to the client's port and ip, that is, establish a link.

bind bind socket and ip port

Bind assigns a local protocol address to the socket. For network protocols, the protocol address is a 32-bit IPv4 address or a 128-bit IPv6 address.
Insert picture description here
The first parameter is the return value of the socket function, and the second and third are the same as described in the connect function. Insert picture description here
Establish two socket objects, one for the server and the other for the client.

Server listen listen queue

listen is only called by the TCP server, and mainly
Insert picture description here
performs two functions: backlog refers to the maximum number of links. For a given listening socket, the kernel maintains two queues:
1. To complete the link queue
2. Insert picture description here
Before the backlog of the uncompleted connection queue, it has been defined as the maximum value of the sum of the two queues. Normally, in a test environment, set backlog to 5. But it is far from enough for modern servers. Remember that backlog cannot be set to 0, which will cause defects in the program. If you don't want other people to connect, you should close this port.

Server-side accept

Accept is called by the server to link the connect request sent by the client, thereby establishing a connection through three waves of hands. Insert picture description here
Please note that if the accept execution is successful, the return value is a new descriptor automatically generated by the kernel, representing the TCP connection with the client. This descriptor is called a connected socket, and the return value of the socket function is called a listening socket. A listening socket sockfd often only generates one in the server program, and it always exists. The connected socket C means that the client and server have completed the three-way handshake. When the client disconnects, the C socket is closed.
Of course, if C<0, it means that the establishment of the link has failed, and it will block and wait for the client to connect.Insert picture description here

write和read

Write and read are two states, representing processing data and receiving data respectively. For example, when the program communicates, usually write is represented by the send system call, and read is usually represented by the recv system call.
Send and recv on the client side: Send and recv on the Insert picture description here
server side:Insert picture description here

Close the socketclose

At this point, the programming process of the TCP socket is basically over, and you only need to close the socket descriptor.

Experimental result

Three-way handshake to establish a link: Insert picture description here
continue to read data and send data from the client: Insert picture description here
server source code:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<assert.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>

int main()
{
    
    
	int sockfd=socket(AF_INET,SOCK_STREAM,0);
	assert(-1!=sockfd);

	struct sockaddr_in saddr,caddr;
	memset(&saddr,0,sizeof(saddr));    //注意memset是取地址

	saddr.sin_family=AF_INET;
	saddr.sin_port=htons(6000);//主机转网络字节,网络是大段;
	saddr.sin_addr.s_addr=inet_addr("127.0.0.1");

	int res=bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
	assert(res!=-1);

	listen(sockfd,5);    //以完成3次握手队列长度是5


	while(1)
	{
    
    
		int len=sizeof(caddr);
		int c=accept(sockfd,(struct sockaddr*)&caddr,&len);
		
		//这里是c也是套接字,类似与上面代码的sockfd;

		if(c<0)
		{
    
    
			continue;
		}
		printf("accept c=%d\n",c);     //链接套接子
		while(1)
		{
    
    
			char buff[128]={
    
    0};
			int n=recv(c,buff,127,0);
			//如果对方关闭了发送,recv返回0;-1是失败
			if(n<=0)
			{
    
    
				break;
			}
			printf("buff=%s\n",buff);
			send(c,"ok",2,0);
		}
		close(c);
	}
}



Client source code:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<assert.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>

int main()
{
    
    
	int sockfd=socket(AF_INET,SOCK_STREAM,0);
	assert(sockfd!=-1);

	struct sockaddr_in saddr;
	memset(&saddr,0,sizeof(saddr));
	saddr.sin_family=AF_INET;
	saddr.sin_port=htons(6000);
	saddr.sin_addr.s_addr=inet_addr("127.0.0.1");

	int res =connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
	assert(res!=-1);

	while(1)
	{
    
    
		char buff[128]={
    
    0};
		printf("input:\n");
		fgets(buff,128,stdin);

		if(strncmp(buff,"end",3)==0)
		{
    
    
			break;
		}
		send(sockfd,buff,strlen(buff),0);
		memset(buff,0,128);
		recv(sockfd,buff,128,0);
		printf("buff=%s\n",buff);
	}
	exit(0);
}

Guess you like

Origin blog.csdn.net/ALITAAAA/article/details/109413541