Simulação de controle de fluxo usando sockets
Publicado por Perfil removido (última atualização em 10/08/2010)
[ Hits: 7.341 ]
Segue uma simulação de controle de buffer de servidor e cliente em socket, efetuando transferência de arquivo do servidor para o cliente, controlando o streaming de bytes entre as máquinas.
//CLIENT #include<sys/socket.h> #include<sys/types.h> #include<netinet/in.h> #include<unistd.h> #include<stdlib.h> #include<stdio.h> #include<string.h> //Taxa de consumo da aplicação #define TAXA_CONSUMO 100 //Controle de socket int sock; struct sockaddr_in address; //Controle de buffer int tamBuf = 0; char *buffer; //Controle de fila int inicio = 0; int fim = 0; int numElem = 0; //Nome do arquivo aberto char arquivo[100]; /* Inserção no buffer, baseada na estrutura de fila estática Recebe: - Elemento a inserir Devolve: - Sucesso da inserção: 0 ou -1 */ int inserir(char elemento) { if (numElem == tamBuf) { return -1; } else { buffer[fim] = elemento; fim = ((fim + 1) % tamBuf); numElem ++; return 0; } } /* Remoção do buffer, baseada na estrutura de fila estática Devolve: - Item removido ou -1 quando vazia */ char remover() { char aux; if (numElem == 0) { return -1; } aux = buffer[inicio]; inicio = ( (inicio + 1) % tamBuf ); numElem --; return aux; } /* Faz a conexão com o servidor; Recebe: -Endereço de IP ou hostname do servidor Devolve: -Sucesso da conexão: 0 ou 1; */ int conectar(char *server) { /* Criação de socket: - AF_INET : famÃlia de protocolos; - SOCK_STREAM : TCP; - 0 : IP; */ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) > 0) { printf("Socket configurado\n"); } address.sin_family = AF_INET; //AF_INET: Arpa Internet Protocols address.sin_port = htons(15000); //htons: Host to Network Short; //cria uma porta para conexão de número 15000 inet_pton(AF_INET,server,&address.sin_addr); //Estabelecimento de conexão if (connect(sock,(struct sockaddr *)&address,sizeof(address)) == 0) { return 1; } return 0; } /* Solicita lista de arquivos disponÃveis no servidor e imprime-a na tela. */ void solicitarLista() { char ask = 'l'; int nbytes, i; char arquivos[2000]; send(sock, &ask, sizeof(char), 0); recv(sock, &nbytes, sizeof(int), 0); recv(sock, arquivos, nbytes, 0); printf("\n\nPressione ENTER para visualizar lista de arquivos disponÃveis: "); getchar(); for (i=0; i<nbytes; i++) { printf("%c", arquivos[i]); } } /* Solicita um determinado arquivo e verifica se ele existe no servidor; Recebe: -Nome do arquivo solicitado; Devolve: -Resposta do servidor quanto à existência do arquivo: 0 ou 1; */ int solicitarArquivo(char *arquivo) { int tam; char c; tam = strlen(arquivo); printf("Arquivo solicitado no servidor..."); send(sock, arquivo, tam+1, 0); recv(sock, &c, 1, 0); if (c=='s') { return 1; } return 0; } /* Adiciona "quant" bytes contidos em "info" no buffer da aplicação. */ int adicionarNoBuffer(char *info, int quant) { int i; for (i=0; i<quant; i++) { inserir(*info); info++; } } /* Consome "quant" bytes do buffer da aplicação, gravando-os em no arquivo apontado por "file" Devolve: - Situação do buffer: 0 (normal), 1 (vazio) ou 2 (cheio); */ int consumirDoBuffer(int quant, FILE* file) { char c; int i, final; final = quant; if (quant>numElem) { final = numElem; } for (i=0; i<final; i++) { c = remover(); fwrite(&c, sizeof(char), 1, file); } if (numElem>=(tamBuf*0.9)) { return 2; } if (numElem<=(tamBuf*0.1)) { return 1; } return 0; } /* Imprime tela do aplicativo e barra de porcentagem de ocupação do buffer; Recebe: - Quantidade ocupada do buffer; - Tamanho total do buffer; */ void imprimirBuffer(int cheio, int tamanho) { float percentual; int i, final; percentual = ((float) cheio) / ((float) tamanho); final = (int) (percentual*79); system("clear"); printf("\n\n\ ___ ___ \n\ /\\__\\ /\\ \\ \n\ ___ /:/ / /::\\ \\ \n\ /\\__\\ /:/ / /:/\\:\\__\\\n\ /:/ / /:/ / ___ /:/ /:/ /\n\ /:/__/ /:/__/ /\\__\\ /:/_/:/ / \n\ /::\\ \\ \\:\\ \\ /:/ / \\:\\/:/ / \n\ /:/\\:\\ \\ \\:\\ /:/ / \\::/__/ \n\ \\/__\\:\\ \\ \\:\\/:/ / \\:\\ \\ \n\ \\:\\__\\ \\::/ / \\:\\__\\ \n\ \\/__/ \\/__/ \\/__/"); printf("\n\n\n\ ____ _____ ____ _____ _ __ __ ___ _ _ ____ \n\ / ___|_ _| _ \\| ____| / \\ | \\/ |_ _| \\ | |/ ___|\n\ \\___ \\ | | | |_) | _| / _ \\ | |\\/| || || \\| | | _ \n\ ___) || | | _ <| |___ / ___ \\| | | || || |\\ | |_| |\n\ |____/ |_| |_| \\_\\_____/_/ \\_\\_| |_|___|_| \\_|\\____|\n"); printf("\n\n\nPERCENTUAL OCUPADO DO BUFFER\n"); for (i=0; i<final; i++) { printf("#"); } for (i=final; i<79; i++) { printf("="); } printf("\n%.2f \% \n", percentual*100); } /* Salva o recebimento de streaming no arquivo apontado por "file"; Recebe: - Ponteiro para o arquivo em que deve-se escrever os bytes recebidos; Devolve: - Sucesso da operação: 0 ou 1; */ int salvarArquivo(FILE *file) { char bytes[200], md5[33], md5client[100]; char ack = 'a'; int nbytes, statusBuf, fimArq; FILE *md5file; if (!file) { return 0; } send(sock, &ack, sizeof(char), 0); //Envia ack do { recv(sock, &nbytes, sizeof(int), 0); //Tamanho do Segmento recv(sock, bytes, nbytes, 0); //Dados do segmento imprimirBuffer(numElem, tamBuf); adicionarNoBuffer(bytes, nbytes); statusBuf = consumirDoBuffer(TAXA_CONSUMO, file); send(sock, &statusBuf, sizeof(int), 0); recv(sock, &fimArq, sizeof(int), 0); } while (fimArq); while (numElem) { consumirDoBuffer(TAXA_CONSUMO, file); imprimirBuffer(numElem, tamBuf); } fclose(file); recv(sock, md5, sizeof(char)*32, 0); md5[32] = 0; printf("\n\nO md5sum do arquivo no servidor é %s", md5); sprintf(md5client, "md5sum %s > %s.md5", arquivo, arquivo); system(md5client); sprintf(md5client, "%s.md5", arquivo); md5file = fopen(md5client, "r"); fread(md5client, sizeof(char), 32, md5file); md5client[32] = 0; printf("\nO md5sum do arquivo recebido é %s", md5client); if (strcmp(md5, md5client)) { printf("\n\nHouve erros na transferência..."); } else { printf("\n\nO arquivo foi transferido de forma consistente..."); } getchar(); return 1; } /* Rotina principal */ int main() { int consumo = TAXA_CONSUMO; char serverName[20]; FILE *file; printf("Digite o IP ou hostname do servidor ao qual deseja de conectar: "); gets(serverName); if (conectar(serverName)) { printf("Conectado ao servidor!\n"); recv(sock, &tamBuf, sizeof(int), 0); //Recebe tamanho do buffer send(sock, &consumo, sizeof(int), 0);//Envia taxa de consumo buffer = (char *) malloc(sizeof(char)*tamBuf); solicitarLista(); printf("Digite um nome de arquivo para solicitar: "); gets(arquivo); if (solicitarArquivo(arquivo)) { printf("\nArquivo encontrado no servidor\n"); printf("\nEscolha o nome para salvar o arquivo: "); gets(arquivo); salvarArquivo(fopen(arquivo, "wb")); } else { printf("Arquivo não encontrado no servidor\n"); } } close(sock); } //SERVER #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<unistd.h> #include<stdlib.h> #include<stdio.h> //Controle de socket int sockServer, sockClient, addrlen; struct sockaddr_in address; //Controle de buffer int FATOR_BUFFER = 0; int tamBuf = 0; char *buffer, *bytes; //Controle de fila int inicio = 0; int fim = 0; int numElem = 0; //Nome do arquivo aberto char arquivo[100]; /* Inserção no buffer, baseada na estrutura de fila estática Recebe: - Elemento a inserir Devolve: - Sucesso da inserção: 0 ou -1 */ int inserir(char elemento) { if(numElem == tamBuf) { return -1; } else { buffer[fim] = elemento; fim = ((fim + 1) % tamBuf); numElem ++; return 0; } } /* Remoção do buffer, baseada na estrutura de fila estática Devolve: - Item removido ou -1 quando vazia */ char remover() { char aux; if (numElem == 0) { return -1; } aux = buffer[inicio]; inicio = ( (inicio + 1) % tamBuf ); numElem --; return aux; } /* Adiciona "quant" bytes, contidos no arquivo apontado por "file", no buffer da aplicação. */ int adicionarNoBuffer(int quant, FILE* file) { int i, lidos; lidos = fread(bytes, sizeof(char), quant, file); for (i=0; i<lidos; i++) { inserir(bytes[i]); } return lidos; } /* Consome "quant" bytes do buffer da aplicação, gravando-os na variável global "bytes"; Devolve: - Situação do buffer: 0 (normal), 1 (vazio) ou 2 (cheio); */ int consumirDoBuffer(int *quant) { int i, final; if (*quant>numElem) { *quant = numElem; } for (i=0; i<(*quant); i++) { bytes[i] = remover(); } if (numElem>=(tamBuf*0.9)) { return 2; } if (numElem<=(tamBuf*0.1)) { return 1; } return 0; } /* Configura o socket, inicia o servidor e espera pela conexão de cliente; Devolve: - 0 : caso em que não houve conexão de clientes; - 1 : caso em que o cliente efetuou a conexão; */ int iniciaServer() { system("clear"); /* Criação de socket: - AF_INET : famÃlia de protocolos; - SOCK_STREAM : TCP; - 0 : IP; */ if ((sockServer = socket(AF_INET, SOCK_STREAM, 0)) > 0) { printf("Socket criado\n"); } address.sin_family = AF_INET; //AF_INET: Arpa Internet Protocols address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(15000); //htons: Host to Network Short; //cria uma porta para conexão de número 15000 //Binding: associação de uma porta a um socket if (bind(sockServer,(struct sockaddr *)&address,sizeof(address)) == 0) { printf("Aguardando conexão...\n"); } //Listening: fica esperando uma conexão; //3: número de clientes que podem esperar na fila listen(sockServer, 3); addrlen = sizeof(struct sockaddr_in); //Abre mais uma porta para a conexão do cliente sockClient = accept(sockServer,(struct sockaddr *)&address,&addrlen); //sockCliente conecta com o cliente, enquanto sockServer espera outras conexões if (sockClient > 0) { return 1; } return 0; } /* Aguarda pela solicitação de arquivo pelo cliente. Ao receber a solicitação verifica a existência do arquivo no servidor e devolve o ponteiro para o arquivo, se o mesmo existir, ou, NULL caso não exista; */ FILE* aguardarSolicitacao() { char c = 's'; char ask, arquivos[2000]; int nbytes; FILE *lista, *file; recv(sockClient, &ask, sizeof(char), 0); if (ask=='l') { system("ls -x > lista"); lista = fopen("lista", "r"); nbytes = fread(arquivos, sizeof(char), 2000, lista); send(sockClient, &nbytes, sizeof(int), 0); send(sockClient, arquivos, nbytes, 0); } recv(sockClient, arquivo, 100, 0); file = fopen(arquivo, "rb"); if (file) { send(sockClient, &c, 1, 0); return file; } c = 'n'; send(sockClient, &c, 1, 0); return NULL; } /* Imprime tela do aplicativo e barra de porcentagem de ocupação do buffer; Recebe: - Quantidade ocupada do buffer; - Tamanho total do buffer; */ void imprimirBuffer(int cheio, int tamanho) { int i, final; float percentual; percentual = ((float) cheio) / ((float) tamanho); final = (int) (percentual*79); system("clear"); printf("\n\n\ ___ ___ \n\ /\\__\\ /\\ \\ \n\ ___ /:/ / /::\\ \\ \n\ /\\__\\ /:/ / /:/\\:\\__\\\n\ /:/ / /:/ / ___ /:/ /:/ /\n\ /:/__/ /:/__/ /\\__\\ /:/_/:/ / \n\ /::\\ \\ \\:\\ \\ /:/ / \\:\\/:/ / \n\ /:/\\:\\ \\ \\:\\ /:/ / \\::/__/ \n\ \\/__\\:\\ \\ \\:\\/:/ / \\:\\ \\ \n\ \\:\\__\\ \\::/ / \\:\\__\\ \n\ \\/__/ \\/__/ \\/__/"); printf("\n\n\n\ ____ _____ ____ _____ _ __ __ ___ _ _ ____ \n\ / ___|_ _| _ \\| ____| / \\ | \\/ |_ _| \\ | |/ ___|\n\ \\___ \\ | | | |_) | _| / _ \\ | |\\/| || || \\| | | _ \n\ ___) || | | _ <| |___ / ___ \\| | | || || |\\ | |_| |\n\ |____/ |_| |_| \\_\\_____/_/ \\_\\_| |_|___|_| \\_|\\____|\n"); printf("\n\n\nPERCENTUAL OCUPADO DO BUFFER\n"); for (i=0; i<final; i++) { printf("#"); } for (i=final; i<79; i++) { printf("="); } printf("\n%.2f \% \n", percentual*100); } /* Envia por um streaming de bytes o arquivo apontado por "file", efetuando o controle de fluxo através do uso do "buffer" e das variáveis addBytes e remBytes; */ void enviarArquivo(FILE *file) { char c, md5[100]; int addBytes = FATOR_BUFFER*2; int remBytes = FATOR_BUFFER; int statusBufClient = 0; int statusBuf = 0; int control = 1; FILE *md5file; if (!file) { return; } sprintf(md5, "md5sum %s > %s.md5", arquivo, arquivo); system(md5); sprintf(md5, "%s.md5", arquivo); md5file = fopen(md5, "r"); fread(md5, sizeof(char), 32, md5file); recv(sockClient, &c, sizeof(char), 0); //Recebe confirmação de inÃcio do { if (!(feof(file))) { adicionarNoBuffer(addBytes, file); } statusBuf = consumirDoBuffer(&remBytes); imprimirBuffer(numElem, tamBuf); send(sockClient, &remBytes, sizeof(int), 0); send(sockClient, bytes, remBytes, 0); recv(sockClient, &statusBufClient, sizeof(int), 0); if (statusBufClient==1) { remBytes = FATOR_BUFFER + (rand() % (FATOR_BUFFER/2)) + (FATOR_BUFFER/2); } if (statusBufClient==2) { remBytes = FATOR_BUFFER - (rand() % (FATOR_BUFFER/4)) - (FATOR_BUFFER/3); } if (statusBuf==1) { addBytes = remBytes*2; } if (statusBuf==2) { addBytes = remBytes/2; } send(sockClient, &numElem, sizeof(int), 0); } while (numElem); send(sockClient, md5, sizeof(char)*32, 0); return; } /* Rotina principal */ int main() { do { printf("\nTamanho do buffer do servidor (em bytes) (mÃn.: 2000): "); scanf("%d", &tamBuf); } while (tamBuf<2000); int tamBufClient = tamBuf/2; buffer = (char *) malloc(sizeof(char)*tamBuf); if (iniciaServer()) { printf("\nConexão estabelecida!"); send(sockClient, &tamBufClient, sizeof(int), 0); //Envia tamanho de buffer recv(sockClient, &FATOR_BUFFER, sizeof(int), 0); // Recebe taxa de consumo do client bytes = (char *) malloc(sizeof(char)*FATOR_BUFFER*2); printf("\nO tamanho do buffer do servidor é: %d", tamBuf); printf("\nO fator de buffer do cliente é: %d", FATOR_BUFFER); enviarArquivo(aguardarSolicitacao()); } else { printf("\nNão foi possÃvel conectar..."); } close(sockClient); close(sockServer); }
Exemplo de Cliente e Servidor Usando Socket no Linux!
Nenhum comentário foi encontrado.
Enviar mensagem ao usuário trabalhando com as opções do php.ini
Meu Fork do Plugin de Integração do CVS para o KDevelop
Compartilhando a tela do Computador no Celular via Deskreen
Como Configurar um Túnel SSH Reverso para Acessar Sua Máquina Local a Partir de uma Máquina Remota
Configuração para desligamento automatizado de Computadores em um Ambiente Comercial
Compartilhamento de Rede com samba em modo Público/Anônimo de forma simples, rápido e fácil
Cups: Mapear/listar todas as impressoras de outro Servidor CUPS de forma rápida e fácil
Criando uma VPC na AWS via CLI
Tem como instalar o gerenciador AMD Adrenalin no Ubuntu 24.04? (11)