Flujo básico de programación de sockets TCP

Descripción general del proceso de programación básico

Para realizar la comunicación entre el cliente y el servidor, el cliente y el servidor deben completarse juntos. Entre ellos, el proceso de programación del servidor TCP y el cliente se muestra en la figura: Inserte la descripción de la imagen aquí
primero, el servidor crea un socket, luego bind vincula el puerto de comunicación y crea una cola de escucha. Después de eso, comenzó el proceso de comunicación. En este momento, el servidor está bloqueado en la aceptación hasta que el cliente tcp tome la iniciativa de conectarse para un protocolo de enlace de tres vías para establecer una conexión. En este momento, la función de escritura del cliente envía una solicitud al servidor, y el servidor lee para leer la solicitud y procesarla. Una vez que se completa el procesamiento, se llama a la función de escritura del servidor para enviar un mensaje de respuesta al cliente, y el cliente recibe el mensaje de respuesta a través de lectura. En este punto, todo el intercambio de datos ha terminado y el cliente puede cerrar de forma activa.

Programación de sockets en el cliente y el servidor

Inserte la descripción de la imagen aquí
La familia suele ser AF_INET según el protocolo IPV4 y AF_INET6 según el protocolo IPv6. El tipo es SOCK_STREAM según el protocolo de transmisión TCP y SOCK_DGRAM según el protocolo UDP. En términos generales, el protocolo de parámetros del socket de función se establece en 0, a menos que se utilice en el socket original.

La función de conexión del cliente establece un enlace con el servidor.

El cliente TCP utiliza la función de conexión para establecer una conexión con el servidor TCP. Inserte la descripción de la imagen aquí
sockfd es el valor de retorno de la función socket. El segundo parámetro es un puntero a la estructura de la dirección del socket y el tercer parámetro es el tamaño de la estructura. Inserte la descripción de la imagen aquí
sin_port es el número de puerto y S_addr es la dirección IP de la red del servidor. A través de este programa, el cliente puede conectarse al puerto y la ip del cliente, es decir, establecer un enlace.

enlazar bind socket y puerto ip

Bind asigna una dirección de protocolo local al socket. Para los protocolos de red, la dirección del protocolo es una dirección IPv4 de 32 bits o una dirección IPv6 de 128 bits.
Inserte la descripción de la imagen aquí
El primer parámetro es el valor de retorno de la función de conector, y el segundo y el tercero son los mismos que se describen en la función de conexión. Inserte la descripción de la imagen aquí
Establezca dos objetos de socket, uno para el servidor y otro para el cliente.

Servidor escucha escucha cola

listen solo es llamado por el servidor TCP y
Inserte la descripción de la imagen aquí
realiza principalmente dos funciones: backlog se refiere al número máximo de enlaces. Para un socket de escucha dado, el kernel mantiene dos colas:
1. Para completar la cola de enlaces.
2. Inserte la descripción de la imagen aquí
Antes de la acumulación de la cola de conexión incompleta, se ha definido como el valor máximo de la suma de las dos colas. Normalmente, en el entorno de prueba, establezca la acumulación en 5. Pero está lejos de ser suficiente para los servidores modernos. Recuerde que la acumulación no se puede establecer en 0, lo que provocará defectos en el programa. Si no desea que otras personas se conecten, debe cerrar este puerto.

Aceptación del lado del servidor

Accept es llamado por el servidor para vincular la solicitud de conexión enviada por el cliente, estableciendo así una conexión a través de tres oleadas de manos. Inserte la descripción de la imagen aquí
Tenga en cuenta que si la ejecución de la aceptación es exitosa, el valor de retorno es un nuevo descriptor generado automáticamente por el kernel, que representa la conexión TCP con el cliente. Este descriptor se denomina socket conectado y el valor de retorno de la función socket se denomina socket de escucha. Un sockfd de socket de escucha a menudo solo genera uno en el programa del servidor, y siempre existe. El conector C conectado significa que el cliente y el servidor han completado el protocolo de enlace de tres vías. Cuando el cliente se desconecta, el conector C se cierra.
Por supuesto, si C <0, significa que el establecimiento del enlace ha fallado, y se bloqueará y esperará a que el cliente se conecte.Inserte la descripción de la imagen aquí

escribir 和 leer

La escritura y la lectura son dos estados, que representan el procesamiento de datos y la recepción de datos, respectivamente. Por ejemplo, cuando el programa se comunica, normalmente la escritura está representada por la llamada al sistema de envío y la lectura normalmente está representada por la llamada al sistema recv.
Enviar y recibir en el lado del cliente: Enviar y recibir en el Inserte la descripción de la imagen aquí
lado del servidor:Inserte la descripción de la imagen aquí

Cerrar el enchufe

En este punto, el proceso de programación del socket TCP básicamente ha terminado y solo necesita cerrar el descriptor del socket.

Resultado experimental

Apretón de manos de tres vías para establecer un enlace: Inserte la descripción de la imagen aquí
continuar leyendo datos y enviar datos desde el cliente: Inserte la descripción de la imagen aquí
código fuente del servidor:

#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);
	}
}



Código fuente del cliente:

#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);
}

Supongo que te gusta

Origin blog.csdn.net/ALITAAAA/article/details/109413541
Recomendado
Clasificación