Envio de dados via socket [RESOLVIDO]

1. Envio de dados via socket [RESOLVIDO]

Judson A. Borges
karvox

(usa Ubuntu)

Enviado em 04/05/2009 - 00:58h

Galera, estou com um problema da seguinte ordem. Preciso enviar dados de um cliente para um servidor via socket. Tipo envio uma matriz nxn e um comando, ordenar, determinante, diagonal principal etc. Só que não consigo enviar dados diferentes de strings como doubles, int entre outros. Só para exemplo eu tentei o seguinte: a aplicação cliente envia dois numeros para o servidor e este calcula a soma dos dois numeros e envia o total para o cliente. Mas não dá certo. Como façço para enviar dados do tipo int via socket? Segue o codigo cliente:

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

int main(int argc, char *argv[]) {

struct sockaddr_in server_addr;
int iSock, num1, num2;
char op[100];

/*if (argc != 2) {
fprintf(stderr, "USAGE: clientsocket <word>\n");
exit(1);
}*/

iSock = (socket(AF_INET, SOCK_STREAM, 0));
if(iSock < 0){
perror("Erro ao criar socket ");
exit(1);
}

//memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(5010);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
bzero(&(server_addr.sin_zero), 8);

if(connect(iSock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0){
perror("Erro ao conectar \n");
exit(1);
}

int iBytes, buffer__;
char buffer_[200];

printf("Digite o primeiro número: ");
scanf("%d", &num1);
//puts("Digite o segundo número: ");
//scanf("%d", &num2);
/*puts("Digite o operador: ");
scanf("%s", &op);*/

puts("====================== Resultado ==========================");

itoa(num1,buffer_,10);
//Enviando dados.
if(send(iSock, buffer_, strlen(num1), 0) < 0){
perror("Erro ao enviar a mensagem \n");
exit(1);
}

// if(send(iSock, num2, strlen(num2), 0) < 0){
// perror("Erro ao enviar a mensagem \n");
// exit(1);
// }

/*if(send(iSock, op, strlen(op), 0) < 0){
perror("Erro ao enviar a mensagem \n");
exit(1);
}*/

//Enviando dados.
//if(send(iSock, buffer_, strlen(buffer_), 0) < 0){
// perror("Erro ao enviar a mensagem \n");
// exit(1);
//}

//Recebendo dados.
if ((iBytes = recv(iSock, buffer__, strlen(buffer__), 0)) < 0){
perror("Erro ao receber mensagem \n");
exit(1);
}

//buffer__[iBytes] = '{TEXTO}';

printf("\nResposta: %d\n", buffer__);

close(iSock);

return EXIT_SUCCESS;
}

código servidor:

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

int main(void) {

int iSock;
struct sockaddr_in server_addr;

iSock = socket(AF_INET, SOCK_STREAM, 0);
if (iSock < 0){
printf("Erro ao criar socket \n");
exit(1);
}

memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(5010);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
//bzero(&(server_addr.sin_zero), 8);

if (bind(iSock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0){
printf("Erro ao executar bind \n");
exit(1);
}

if (listen(iSock, 1) < 0){
printf("Erro ao escutar na porta 5010 \n");
exit(1);
}

while (1){

int iFd, total, op, num1 = 10, num2;
struct sockaddr_in client_addr;
socklen_t sin_size;
char szMessage[200];

sin_size = sizeof(struct sockaddr_in);

if ((iFd = accept(iSock, (struct sockaddr *) &client_addr, &sin_size)) < 0) {
perror("Erro ao estabelecer conexão com o cliente \n");
exit(1);
}

printf("Cliente conectado: %s\n", inet_ntoa(client_addr.sin_addr));

/*if (send (iFd, inet_ntoa(client_addr.sin_addr), strlen(inet_ntoa(client_addr.sin_addr)), 0) < 0){
perror("Endereço do cliente desconhecido ");
exit(1);
}*/

int Bytes_rec, Bytes_rec2, Bytes_rec3;

if ((Bytes_rec = recv(iFd, atoi(num1), strlen(num1), 0)) < 0){
printf("Erro ao receber mensagem do cliente \n");
exit(1);
}

//if ((Bytes_rec2 = recv(iFd, num2, strlen(num2), 0)) < 0){
// printf("Erro ao receber mensagem do cliente \n");
// exit(1);
//}

/*if ((Bytes_rec3 = recv(iFd, op, strlen(op), 0)) < 0){
printf("Erro ao receber mensagem do cliente \n");
exit(1);
}*/

//bloco original
//if ((Bytes_rec = recv(iFd, szMessage, 200, 0)) < 0){
// printf("Erro ao receber mensagem do cliente \n");
// exit(1);
//}

szMessage[Bytes_rec] = '{TEXTO}';
//num1[Bytes_rec] = '{TEXTO}';
//num2[Bytes_rec2] = '{TEXTO}';
//num3[Bytes_rec3] = '{TEXTO}';

//num1[Bytes_rec] = '{TEXTO}';
//num2[Bytes_rec] = '{TEXTO}';
//op[Bytes_rec] = '{TEXTO}';

total = num1 + num2;

/*switch(op){
//soma
case 1: {
total = num1 + num2;
break;
}
case 2: {
//subtração
total = num1 - num2;
break;
}
case 3: {
//multiplicação
total = num1 * num2;
break;
}
case 4: {
//divisão
total = num1 / num2;
break;
}
default:
printf("Error: Invalid option!");
break;
}*/


//mess_rec[Bytes_r] = '{TEXTO}';

//memset(szMessage, 0, sizeof(szMessage));
//szMessage[0] = "Recebi Judson\n";
//strcpy(szMessage, "Devolvendo o DIA\n");

//bloco original
//if (send(iFd, szMessage, 200, 0) < 0){
// printf("Erro ao enviar mensagem para o cliente \n");
// exit(1);
//}

if (send(iFd, atoi(num1), strlen(num1), 0) < 0){
printf("Erro ao enviar mensagem para o cliente \n");
exit(1);
}

close(iFd);
}
return EXIT_SUCCESS;
}



  


2. MELHOR RESPOSTA

João Marcos Menezes
stremer

(usa Arch Linux)

Enviado em 07/05/2009 - 08:19h

agora que to com mais tempo (mas ainda não deu pra testar)... só pra te explicar melhor...
o socket é um tipo de stream... ou seja... uma sequencia de bytes enviados de um lado e lido do outro e vice-versa... como quase tudo no mundo da informática...
o send ou recv basicamente recebem um ponteiro como parâmetro que é um endereço de memória onde estão os dados, e uma quantidade de bytes que vai ler dali pra frente... ou seja... passando quanquer endereço e uma quantidade de bytes... ele le e envia ou recebe em um outro ponteiro... (por isso o parâmetro dele é void *)

A quantidade vai depender do tipo... uma string (ou char *) já é um ponteiro, e por isso que na hora de mandar usa-se strlen(variavel) para pegar o total de bytes até o caracter nulo!

Qualquer outro tipo primitivo que não seja ponteiro (por ex. a int ou double), é preciso passar para ele o endereço da memória (por isso usar o &), e então a quantidade de bytes ou melhor... tamanho do tipo...

Procure no google sobre Intel Integer e de uma lida... para ver teoricamente o que é um inteiro!

Volto a falar... não testei o código (já que geralmente uso socket para alguns protocolos web que trabalham com string)... mas basicamente em C é assim!

Boa sorte!

3. Envio de dados via socket

Anderson Eugênio Silva da Costa
Andersoneugenio

(usa Outra)

Enviado em 06/05/2009 - 17:14h

Karvox, o prof. Valentim falou que era melhor usar string... que ficaria mais fácil.


4. amigo

João Marcos Menezes
stremer

(usa Arch Linux)

Enviado em 06/05/2009 - 19:02h

Eu nunca precisei mandar int, mas teoricamente não há problemas... to sem tempo agora para testar, mas tente:

if(send(iSock, &num2, sizeof(int), 0) < 0){

ou se prefererir ao invésd e sizeof(int) coloque 4, afinal um int tem o tamanho de 4 bytes ou 32 bits



5. Re: Envio de dados via socket [RESOLVIDO]

Elgio Schlemer
elgio

(usa OpenSuSE)

Enviado em 08/05/2009 - 22:09h

A resposta do stremer está perfeita e assino embaixo.

para não ficar sem contribuir em nada, ainda tem outra solução: converte para string!

No cliente (quem envia)

char buf[1000];

sprintf(but,"%d %d", num1, num2);
send(iFd, buf, strlen(buf),0);

No servidor:
Bytes_rec = recv(iFd, buf, 1000, 0);

sscanf(buf, "%d "%d", &num1, &num2);

mas isto só porque o stremer saiu na frente e queimou a solução que eu daria... ;-)


6. Re: Envio de dados via socket [RESOLVIDO]

Marcelo A. B. Slomp
mslomp

(usa Slackware)

Enviado em 08/05/2009 - 22:22h

permitam-me também contribuir com meus 2 centavos :D

não esquecer da ordem dos bytes, pois nunca se sabe se do outro lado teremos little ou big endian. então, sempre converta o int com htonl antes de enviar, e 'desconverta' com ntohl após receber.


7. Re: Envio de dados via socket [RESOLVIDO]

Elgio Schlemer
elgio

(usa OpenSuSE)

Enviado em 08/05/2009 - 22:24h

Caracas, tem razão!!

Isto pode derrubar a versão de enviar os bytes crus do int!
Sem falar que pode ter máquinas onde o tamanho do int não é 4 bytes!!

BOA!


8. Re: Envio de dados via socket [RESOLVIDO]

Marcelo A. B. Slomp
mslomp

(usa Slackware)

Enviado em 08/05/2009 - 22:31h

verdade. para contornar a questão do tamanho do int e manter a portabilidade, pode-se usar um tipo int32_t, int64_t, etc, a gosto do freguês.


9. ae

João Marcos Menezes
stremer

(usa Arch Linux)

Enviado em 13/05/2009 - 18:14h

não entrei nos detalhes dos tipos de int... pois a pergunta era mais focada em tipos primitivos...
mas legal vocês terem citado... inclusive isso vale para muitas outras coisas (não somente socket)...


10. RESOLVIDO

Judson A. Borges
karvox

(usa Ubuntu)

Enviado em 23/05/2009 - 20:26h

Bom galera, quero agradeçer a toda a rapaziada que me ajudou e especialmente ao STREMER que com a dica dele consegui resolver o problema. Então ficou assim:

Aqui o servidor recebendo os dados

...

if ((iBytes = recv(iSock, &impar, sizeof(int), 0)) < 0){
perror("Erro ao receber mensagem \n");
exit(1);
}

//*buff_impar[iBytes] = '{TTEXTO}';
...


Aqui enviando os dados

...
int impares;

if (send(iFd, &impares, sizeof(int), 0) < 0){
printf("Erro ao enviar mensagem para o cliente \n");
exit(1);
}
...


Simplesmente com isso resolveu a questão de enviar e receber inteiros ou array de inteiros via socket. No meu caso eu recebi uma matriz de char e converti em uma matriz de inteiros, fiz algumas operações que necessitei e enviei as veráveis resultantes como vocês veem acima. Galera muito obrigado a todos vocês pela ajuda. Qualquer coisa estamos aí!


11. Re: Envio de dados via socket [RESOLVIDO]

André
andrezc

(usa Debian)

Enviado em 23/05/2009 - 20:38h

: )