Jump to content
Shoxsz

Sockets - Erro recv

Recommended Posts

Shoxsz

Olá pessoal, estava fazendo um programa em C usando sockets para ler um diretorio e enviar ao ciente os arquivos do diretorio, o problema é que no recebimento da mensagem sempre da erro! já peguei alguns exemplos na internet iguais ao meu e eles funcionam perfeitamente bem, mas quando volto pro meu programa, ele nunca recebe a mensagem do cliente:

...
    listen(sock, 10);
    printf("Aguardando conexao...\n");
    if((sockc = accept(sock, (SOCKADDR*)&cliente, &t) == -1))
    {
        perror("accept");
        return 0;
    }
    printf("Cliente conectado!\n");
    while(1)
    {
        b = recv(sockc, diretorio, MAX_DIR, 0);
...

estou fazendo algo de errado no recebimento da mensagem??

Edited by pmg

Share this post


Link to post
Share on other sites
Shoxsz

cara, eu sei disso, essa é só a parte para mostrar que eu já fiz até o bind e estou utilizando 2 descritores para os sockets, um pro sevidor e o outro retornado pela função accept

Share this post


Link to post
Share on other sites
HappyHippyHippo

cara, eu sei disso, essa é só a parte para mostrar que eu já fiz até o bind e estou utilizando 2 descritores para os sockets, um pro sevidor e o outro retornado pela função accept

pois, mas não apresentaste o código, pois não ?

como sei se está bem ?

como sei que o que está para trás se encontra correcto, e andas a fazer chamadas com um descritor válido ?

do código que vejo, não fazes uma única sequer validação de chamada, por isso só posso assumir que o mesmo não é feito no código não apresentado


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
Shoxsz

aqui está o código:

#include <stdio.h>
#include <winsock.h>
#include <dirent.h>
#define MAX_DIR 100
#define PADRAO 4700
#define BYTES_POR_VEZ 500
#define E404 "Diretorio nao encontrado"
#define DIR_OK "Diretorio encontrado"
#define INICIO "inicio"
WSADATA wsa;
SOCKET sock, sockc;
SOCKADDR_IN serv, cliente;
FILE* arq;//Ultimo arquivo encontrado no diretório
DIR* dir;//Diretório principal
DIR* sec;//Diretório que secundário
struct dirent* at;
int ler_diretorio();
int ler_arquivo(char*, int);
int cabecalho(const char*, int);
int tamanho_arquivo();
int main()
{
char diretorio[MAX_DIR], buffer[bYTES_POR_VEZ];
int b;
while(1)
{
 printf("Iniciando servidor...\n");
 if(WSAStartup(MAKEWORD(1, 1), &wsa) == -1)
 {
	 perror("WSAStartup");
	 return 0;
 }
 if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
 {
	 perror("socket");
	 return 0;
 }
 serv.sin_family = AF_INET;
 serv.sin_port = htons(PADRAO);
 serv.sin_addr.s_addr = INADDR_ANY;
 int t = sizeof(serv);
 if(bind(sock, (SOCKADDR*)&serv, t) == -1)
 {
	 perror("bind");
	 return 0;
 }
 listen(sock, 1);
 printf("Aguardando conexao...\n");
 if((sockc = accept(sock, (SOCKADDR*)&cliente, &t) == -1))
 {
	 perror("accept");
	 return 0;
 }
 printf("Cliente conectado!\n");
 while(1)
 {
b = recv(sockc, diretorio, MAX_DIR, 0);
	 if(b < 0)
	 {
		 perror("recv");
		 return 0;
	 }
	 else if(b == 0)
	 {
		 printf("Conexao perdida!\n");
		 return 0;
	 }
	 else
	 {
		 diretorio[b] = '\0';
		 printf("Diretorio para leitura: %s\n", diretorio);
	 }
	 dir = opendir(diretorio);
	 //erro
	 if(dir == NULL)
	 {
		 //Enviar mensagem de erro
		 send(sockc, E404, strlen(E404), 0);
		 printf("%s\n", E404);
		 continue;
	 }
	 //Ler os arquivos do diretório atual
	 while(ler_diretorio() == 1)
	 {
		 //Abrir o arquivo atual
		 arq = fopen(at->d_name, "r");
		 if(arq == NULL)
		 {
			 printf("Falha ao abrir arquivo %s\n", at->d_name);
			 continue;
		 }
		 //Mensagem indicando o inicio de um arquivo
		 if(cabecalho(at->d_name, tamanho_arquivo()) == -1)
		 {
			 printf("Falha ao enviar arquivo %s\n", at->d_name);
			 continue;
		 }
		 //ler arquivo e enviar
		 while(ler_arquivo(buffer, BYTES_POR_VEZ) > 0)
		 {
			 send(sockc, buffer, strlen(buffer), 0);
		 }
		 fclose(arq);
	 }
 }
}
return 0;
}

int ler_diretorio()
{
if((at = readdir(sec)))
 return 1;
return 0;
}
int ler_arquivo(char* buffer, int tam)
{
int i;
for(i = 0; i < tam; i++)
{
 if(!feof(arq))
	 break;
 buffer[i] = fgetc(arq);
}
buffer[i] = '\0';
return i;
}
///Enviar o cabecalho indicando inicio de arquivo para o cliente
int cabecalho(const char* arquivo, int tam)
{
char msg[strlen(arquivo) + strlen(INICIO) + 2];
sprintf(msg, "%s %s", INICIO, arquivo);
if(send(sockc, msg, strlen(msg), 0) <= 0)
 return -1;
itoa(tam, msg, 10);
//Enviar o tamanho do arquivo a ser enviado
if(send(sockc, msg, strlen(msg), 0) <= 0)
 return -1;
return 1;
}
int tamanho_arquivo()
{
fseek(arq, 0, SEEK_END);
int t = ftell(arq);
rewind(arq);
return t;
}

Edited by Shoxsz

Share this post


Link to post
Share on other sites
HappyHippyHippo

o código parece correcto, mas para dançar o tango, são necessários 2

e o código do cliente ?


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
Shoxsz

aqui esta:

#include <stdio.h>
#include <winsock.h>
#define MASTER "192.168.1.50"
#define MAX_DIR 100
#define PADRAO 4700
#define BYTES_POR_VEZ 500
#define E404 "Diretorio nao encontrado"
#define DIR_OK "Diretorio encontrado"
#define INICIO "inicio"
WSADATA wsa;
SOCKET sock;
SOCKADDR_IN info;
int main()
{
   char ip[16];
   char diretorio[MAX_DIR];
   char buffer[bYTES_POR_VEZ];
   if(WSAStartup(MAKEWORD(2, 2), &wsa) == -1)
   {
       perror("WSAStartup");
       return 0;
   }
   if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
   {
       perror("socket");
       return 0;
   }
   info.sin_family = AF_INET;
   info.sin_port = htons(PADRAO);
   printf("IP para conexao: ");
   fflush(stdin);
   scanf("%s", ip);
   ip[16] = '\0';
   if(strcmp(ip, "MASTER") == 0)
       strcpy(ip, MASTER);
   info.sin_addr.s_addr = inet_addr(ip);
   //Conectar
   if(connect(sock, (SOCKADDR*)&info, sizeof(info)) == -1)
   {
       perror("connect");
       return 0;
   }
   printf("Conectado!\n");
   int ok=0;
   do
   {
       printf("Diretorio a ser transferido: ");
       fflush(stdin);
       scanf("%s", diretorio);
       if(strlen(diretorio) > MAX_DIR)
       {
           printf("Nome do diretorio muito grande!\n");
       }
       ok = 1;
   }while(!ok);
   printf("Enviando requisicao de diretorio\n");
   if(send(sock, diretorio, strlen(diretorio), 0) <= 0)
   {
       printf("Falha ao enviar diretorio!\n");
       perror("send");
       return 0;
   }
   printf("Requisicao enviada!");
   printf("Aguardando resposta...\n");
   //teste para ver como a resposta chega
   while(recv(sock, buffer, BYTES_POR_VEZ, 0) > 0)
   {
       printf("%s", buffer);
   }
   return 0;
}

Edited by brunoais
geshi

Share this post


Link to post
Share on other sites
pikax

Porque que estas a usar versoes diferentes de sockets??

Usa portas diferentes para o cliente e para o server


Por muito mais que que estude só aprendo uma coisa, que ainda tenho muita coisa para aprender.

A beleza de um código está em decompor problemas complexos em pequenos blocos simples.

"learn how to do it manually first, then use the wizzy tool to save time."

"Kill the baby, don't be afraid of starting all over again. Fail soon, learn fast."

Share this post


Link to post
Share on other sites
Shoxsz

a sim, as versões eu troquei pra testar a diferença, mas ainda sim se forem iguais dava erro, mas as portas são as mesmas, a constante definida la em cima-> PADRAO(4700)

Share this post


Link to post
Share on other sites
HappyHippyHippo

então tens ai o problema ... as aplicações necessitam de correr em portas diferentes

é normal deixar o sistema operativo deixar escolher uma porta aleatória para o cliente, visto este não necessitar de uma porta específica


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
Shoxsz

elas devem usar a mesma porta para comunicação, eu troquei as portas e ele nem chegam a se conectar, o meu problema é na leitura dos dados.

Edited by Shoxsz

Share this post


Link to post
Share on other sites
HappyHippyHippo

elas devem usar a mesma porta para comunicação, eu troquei as portas e ele nem chegam a se conectar, o meu problema é na leitura dos dados.

errado, não podes ter duas aplicações penduradas na mesma porta ...

se não obtiveste ligação com a alteração é porque usaste uma porta já em uso


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
Shoxsz

então eu devo conectar o meu cliente na porta 30000(por exemplo) e o servidor na porta 28000(por exemplo)?

Share this post


Link to post
Share on other sites
Shoxsz

co um port scanner encontrei dus portas que não estavam em uso, tentei conectar por elas, mas não funcionou, as portas são:

39040 para o servidor e 39039 para o cliente

Share this post


Link to post
Share on other sites
HappyHippyHippo

estive a ver melhor o teu código ...

à definição PADRAO que tens tem significados diferentes nas duas aplicações

- servidor : porta em que o servidor se encontra à escuta

- cliente : porta do servidor

conclusão : sim, necessitas de ter os dois valores iguais


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.