Fluxo de programação de soquete TCP básico

Visão geral do processo básico de programação

Para realizar a comunicação entre o cliente e o servidor, o cliente e o servidor precisam ser concluídos juntos. Dentre eles, o processo de programação do servidor TCP e do cliente é mostrado na figura: Insira a descrição da imagem aqui
primeiro, o servidor cria um soquete, em seguida, vincula a porta de comunicação e cria uma fila de escuta. Depois disso, iniciou-se o processo de comunicação. Nesse momento, o servidor é bloqueado na aceitação até que o cliente tcp tome a iniciativa de se conectar para um handshake de três vias para estabelecer uma conexão. Nesse momento, a função de gravação do cliente envia uma solicitação ao servidor, e o servidor lê para ler a solicitação e processá-la. Após a conclusão do processamento, a função de gravação do servidor é chamada para enviar uma mensagem de resposta ao cliente, e o cliente recebe a mensagem de resposta por meio de leitura. Nesse ponto, toda a troca de dados termina e o cliente pode desligar ativamente.

Programação de soquete no cliente e servidor

Insira a descrição da imagem aqui
A família é geralmente AF_INET sob o protocolo IPV4 e AF_INET6 sob o protocolo IPv6. O tipo é SOCK_STREAM no protocolo de transmissão TCP e SOCK_DGRAM no protocolo UDP. De modo geral, o protocolo de parâmetro do soquete de função é definido como 0, a menos que seja usado no soquete original

A função de conexão do cliente estabelece um link com o servidor

O cliente TCP usa a função de conexão para estabelecer uma conexão com o servidor TCP. Insira a descrição da imagem aqui
sockfd é o valor de retorno da função de soquete. O segundo parâmetro é um ponteiro para a estrutura de endereço de soquete e o terceiro parâmetro é o tamanho da estrutura. Insira a descrição da imagem aqui
sin_port é o número da porta e S_addr é o endereço IP da rede do servidor. Através deste programa, o cliente pode se conectar à porta e ip do cliente, ou seja, estabelecer um link.

bind bind socket e porta ip

O Bind atribui um endereço de protocolo local ao soquete. Para protocolos de rede, o endereço de protocolo é um endereço IPv4 de 32 bits ou um endereço IPv6 de 128 bits.
Insira a descrição da imagem aqui
O primeiro parâmetro é o valor de retorno da função de soquete, e o segundo e o terceiro são os mesmos descritos na função de conexão. Insira a descrição da imagem aqui
Estabeleça dois objetos de soquete, um para o servidor e outro para o cliente.

Servidor escuta fila de escuta

listen só é chamado pelo servidor TCP e
Insira a descrição da imagem aqui
executa principalmente duas funções: backlog se refere ao número máximo de links. Para um determinado soquete de escuta, o kernel mantém duas filas:
1. Para completar a fila de link
2. Insira a descrição da imagem aqui
Antes do backlog da fila de conexão incompleta, ele foi definido como o valor máximo da soma das duas filas. Normalmente, no ambiente de teste, defina o backlog como 5. Mas está longe de ser suficiente para servidores modernos. Lembre-se de que o backlog não pode ser definido como 0, o que causará defeitos no programa. Se você não quiser que outras pessoas se conectem, feche esta porta.

Aceitar do lado do servidor

Aceitar é chamado pelo servidor para vincular a solicitação de conexão enviada pelo cliente, estabelecendo assim uma conexão por meio de três ondas de mãos. Insira a descrição da imagem aqui
Observe que se a execução da aceitação for bem-sucedida, o valor de retorno é um novo descritor gerado automaticamente pelo kernel, representando a conexão TCP com o cliente. Esse descritor é chamado de soquete conectado e o valor de retorno da função de soquete é chamado de soquete de escuta. Um soquete de escuta sockfd geralmente gera apenas um no programa do servidor e sempre existe. O soquete C conectado significa que o cliente e o servidor concluíram o handshake triplo.Quando o cliente se desconecta, o soquete C é fechado.
Obviamente, se C <0, significa que o estabelecimento do link falhou, e ele irá bloquear e esperar que o cliente se conecte.Insira a descrição da imagem aqui

escrever 和 ler

A gravação e a leitura são dois estados, representando o processamento de dados e o recebimento de dados, respectivamente. Por exemplo, quando o programa se comunica, geralmente a escrita é representada pela chamada do sistema de envio e a leitura é geralmente representada pela chamada do sistema recv.
Enviar e receber no lado do cliente: Enviar e receber no lado do Insira a descrição da imagem aqui
servidor:Insira a descrição da imagem aqui

Feche o soquete

Neste ponto, o processo de programação do soquete TCP basicamente acabou, e você só precisa fechar o descritor do soquete.

Resultado experimental

Aperto de mão de três vias para estabelecer um link: Insira a descrição da imagem aqui
continuar a ler dados e enviar dados do cliente: Insira a descrição da imagem aqui
código-fonte do 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-fonte do 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);
}

Acho que você gosta

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