Simulação de controle de fluxo usando sockets
Publicado por Perfil removido (última atualização em 10/08/2010)
[ Hits: 7.386 ]
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); }
Nenhum comentário foi encontrado.
Passkeys: A Evolução da Autenticação Digital
Instalação de distro Linux em computadores, netbooks, etc, em rede com o Clonezilla
Título: Descobrindo o IP externo da VPN no Linux
Armazenando a senha de sua carteira Bitcoin de forma segura no Linux
Enviar mensagem ao usuário trabalhando com as opções do php.ini
Instalando Brave Browser no Linux Mint 22
vídeo pra quem quer saber como funciona Proteção de Memória:
Encontre seus arquivos facilmente com o Drill
Mouse Logitech MX Ergo Advanced Wireless Trackball no Linux
Compartilhamento de Rede com samba em modo Público/Anônimo de forma simples, rápido e fácil
Programa duplicado no "Abrir com" e na barra de pesquisa do ... (1)
VMs e Interfaces de Rede desapareceram (13)
Como abrir o pycharm no linux [RESOLVIDO] (4)