Simulação de controle de fluxo usando sockets
Publicado por Perfil removido (última atualização em 10/08/2010)
[ Hits: 7.615 ]
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);
}
Calcular Broadcast e IPs disponíveis
Nenhum comentário foi encontrado.
Monitorando o Preço do Bitcoin ou sua Cripto Favorita em Tempo Real com um Widget Flutuante
IA Turbina o Desktop Linux enquanto distros renovam forças
Como extrair chaves TOTP 2FA a partir de QRCODE (Google Authenticator)
Ativando e usando "zoom" no ambiente Cinnamon
Vídeo Nostálgico de Instalação do Conectiva Linux 9
Como realizar um ataque de força bruta para desobrir senhas?
Estou tentando ser legalista, mas tá complicado! (8)
Thinkpads são bons mesmo ?! (0)
Queda no serviços da Cloudflare, alguns sites estão fora do ar. (1)









