[HELP] Cliente/Servidor em C - PROBLEMAS

1. [HELP] Cliente/Servidor em C - PROBLEMAS

Vinícius Cardoso
WizardTech

(usa Outra)

Enviado em 11/06/2019 - 23:39h

Eu estou criando uma aplicação cliente/servidor em C no linux. O propósito é bem simples, saber se vale mais a pena alugar ou vender um imóvel.O usuário digita o valor do aluguel, os meses que irá alugar e o valor que irá vender e o servidor faz as contas e devolve o resultado. Tudo está dentro de um do while para ficar infinito, no final o usuário digita CONTINUAR para testar outros valores e SAIR para encerrar a conexão. Mas está com um problema que não consigo identificar. A primeira vez que comparamos valores, o servidor retorna o resultado correto(alugar ou vender), porém a partir da segunda vez ao digitar CONTINUAR, ele sempre retorna resultados errados. Eu suspeito que esteja armazenando dados na variáveis erradas a partir da segunda vez, coloquei uns prints no meio do código para mostrar os valores e tem divergência.E também tentei zerar as variáveis no começo e usar vários bzero e fflush, mas sem resultado. Mas não tenho certeza de nada. Podem me ajudar?

Código do cliente:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>

int main ()
{
struct sockaddr_in sock;
int con, sockid,numbytes;
char resposta[10];
char buf[100];
char aluguel[10];
char venda[10];
char meses[2];
sockid = socket(AF_INET, SOCK_STREAM, 0);

bzero(&(sock),sizeof(sock));

sock.sin_family = AF_INET;
sock.sin_port = htons(9012);
inet_pton(AF_INET, "127.0.0.1",&sock.sin_addr);

con=connect(sockid,(struct sockaddr*)&sock,sizeof(sock));
do{
if(con>=0)
{
printf("=====================================================\n");
printf("Descubra se vale a pena vender ou alugar seu imóvel\n");
printf("=====================================================\n");
printf("Digite por quanto voce quer alugar: \n");
scanf("%s", &aluguel);

printf("=====================================================\n");

if(send(sockid,aluguel,strlen(aluguel),0)==-1)
{
printf("Erro ao enviar mensagem\n");
close(sockid);
}
printf("Digite por quantos meses ira alugar : \n");
scanf("%s", &meses);

printf("=====================================================\n");

if(send(sockid,meses,strlen(meses),0)==-1)
{
printf("Erro ao enviar mensagem\n");
close(sockid);
}
printf("Digite por quanto quer vender: \n");
scanf("%s", &venda);

printf("=====================================================\n");

if(send(sockid,venda,strlen(venda),0)==-1)
{
printf("Erro ao enviar mensagem \n");
close(sockid);
}


bzero(&buf,sizeof(buf));
if((numbytes=recv(sockid,buf,100,0)==-1))
{
printf("Erro ao receber a mensagem\n");
}

printf("Vale mais a pena: %s\n",buf);
printf("Digite SAIR para sair ou CONTINUAR para continuar a comparar.\n");
scanf("%s",&resposta);
fflush(stdin);
if(send(sockid,resposta,strlen(resposta),0)==-1)
{
printf("Erro ao enviar mensagem\n");
close(sockid);
}

if(strcmp(resposta,"CONTINUAR")==0)
{
continue;
}

}
}while(strcmp(resposta,"SAIR")!=0);
close(sockid);

}



Código do servidor:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>

int main ()
{
int sockid;
struct sockaddr_in servidor;
int client,numbytes;
float convertido;
float convertido1;
float convertido2;
char passar[10];
char buf[100];
char buf1[100];
char buf2[100];
float resultado;
char resposta[10];


sockid = socket(AF_INET, SOCK_STREAM,0);
if(sockid==-1)
{
printf("Não foi possivel criar o socket");
exit(1);
}

servidor.sin_family= AF_INET;
servidor.sin_addr.s_addr = htonl(INADDR_ANY);
servidor.sin_port = htons(9012);

if(bind(sockid,(struct sockaddr*)&servidor, sizeof(servidor))<0)
{
printf("Falhou ao associar a porta\n");
}

listen(sockid, 3);
int c, new_socket;

while(1)
{
c = sizeof(struct sockaddr_in);
new_socket = accept(sockid, (struct sockaddr *)&client,(socklen_t *)&c);

if(new_socket <=0)
{
printf("Falhou ao aceitar o conector\n");
continue;
}

while(1){
printf("Conexão aceita\n");
fflush(stdin);
resultado = 0;
convertido = 0;
convertido1 = 0;
convertido2 = 0;
bzero(&buf,sizeof(buf));
if((numbytes=recv(new_socket,buf,100,0)==-1))
{
printf("Erro ao receber a mensagem\n");
}

convertido = atof(buf);


bzero(&buf1,sizeof(buf1));
if((numbytes=recv(new_socket,buf1,100,0)==-1))
{
printf("Erro ao receber mensagem\n");
}
convertido1 = atof(buf1);
printf(buf1);


bzero(&buf2,sizeof(buf2));
if((numbytes=recv(new_socket,buf2,100,0)==-1))
{
printf("Erro ao receber mensagem\n");
}
convertido2 = atof(buf2);
printf(buf2);



resultado = convertido*convertido1;

if(resultado>convertido2)
{
sprintf(passar, "Alugar");
}
else
{
sprintf(passar,"Vender");
}
if(send(new_socket,passar,strlen(passar),0)==-1)
{
printf("Erro ao enviar a mensagem\n");
close(new_socket);

}
bzero(&resposta,sizeof(resposta));
if((numbytes=recv(new_socket,resposta,strlen(resposta),0)==-1))
{
printf("Erro ao receber a mensagem\n");
}
fflush(stdin);
if(strcmp(resposta,"SAIR")==0)
{

close(new_socket);
break;

}

}
}
}



  


2. Re: [HELP] Cliente/Servidor em C - PROBLEMAS

Paulo
paulo1205

(usa Ubuntu)

Enviado em 13/06/2019 - 10:52h

Você possivelmente está tendo problemas causados por estratégias de buffering de recepção e transmissão de pacotes, junto com sockets que provavelmente são blocantes.

Só para exemplificar o problema, peguemos um caso. Um lado escreve strlen(meses) bytes, e o outro espera ler 100 bytes. Se strlen(meses) for menor do que 100, o que é bem provável, o lado que está esperando pelos 100 bytes vai continuar esperando, até que haja um total de 100 bytes ou que ocorra um evento externo que interrompa a leitura.

Como corrigir isso?

O jeito mais simples é usar tamanhos fixos em todas as suas mensagens.

Outro jeito relativamente simples é dizer o tamanho de cada mensagem antes de a transmitir, e ler o tamanho antes de receber os dados.
uint32_t msglen=strlen(meses);
uint32_t netmsglen=htonl(msglen);
send(socket, &netmsglen, sizeof netmsglen, 0);
send(socket, meses, msglen, 0);

uint32_t msglen, netmsglen;
if(recv(socket, &netmsglen, sizeof netmsglen, 0)!=sizeof netmsglen){ /* Erro de protocolo: informação de tamanho de mensagem truncada. */ }
msglen=ntohl(netmsglen);
if(recv(socket, meses, msglen, 0)!=msglen) { /* Erro de protocolo: faltaram bytes da mensagem. */ }


Outra forma é passar verificar se há dados a ler antes de tentar lê-los. Isso pode ser feito tanto com sockets blocantes quanto com não-blocantes, por meio de select() ou poll(), e a quantidade de bytes disponíveis para leitura pode ser obtida com a função FIONREAD de ioctl().


... “Principium sapientiae timor Domini, et scientia sanctorum prudentia.” (Proverbia 9:10)






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts