Hello, i'm building a client-server application using sockets in C. I'm trying to send a structure through a socket, but the values after "deserialization" (the use of htonl-ntohl) come adulterated and i dont know why. Maybe you could help me? Here is the code:
Server.c
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h> // O_CREAT | O_TRUNC ...ETC
#include "db.h"
#include <pthread.h>
#include "query.h"
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
//DBHANDLE database;
#define MAXPENDING 5
#define RCVBUFSIZE 32
void HandleTcpClient(void * data)
{
QUERY * qry = (QUERY *) data;
int codigo_produto = ntohs(qry->codigo_produto);
unsigned long preco = ntohl(qry->preco);
int quantidade = ntohs(qry->quantidade);
qry->codigo_produto = codigo_produto;
qry->preco = preco;
qry->quantidade = quantidade;
//database = db_open("aux", O_CREAT | O_TRUNC | O_RDWR, 0666);
printf("Codigo Produto: %d\n Preço: %u\n Quantidade: %d\n",qry->codigo_produto,qry->preco,qry->quantidade);
//close((clntSock));
free(qry);
exit(0);
}
int main(int argc, char * argv[]) {
int servSock; //id do socket do servidor -> retorno de socket()
int clntSock; //id do socket do cliente
pthread_t thread1;
struct sockaddr_in servAddr; //dados relativos ao socket do servidor(ip,porto)
struct sockaddr_in clntAddr; //dados relativos ao socket do cliente
unsigned short servPort;
unsigned int clntLen;
int recvMsgSize;
QUERY * query; //Estrutura a passar à função handletcpclient
query = (QUERY *) malloc(sizeof(QUERY));
memset(query,0,sizeof(QUERY));
if(argc !=2 )
{
fprintf(stderr,"Usage: %s <Server Port>\n",argv[0]);
exit(1);
}
servPort = atoi(argv[1]);
if((servSock = socket(AF_INET,SOCK_STREAM,0)) < 0) //Criação do socket do servidor
{
perror("Error with Socket()");
exit(1);
}
/* Preenchimento dos dados relativos ao socket criado, para passar às funções bind e accept */
/*Registar endereço local de modo a que os clientes nos possam contactar*/
memset(&servAddr,0,sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(servPort);
if(bind(servSock,(struct sockaddr*)&servAddr,sizeof(servAddr)) < 0)
{
perror("Error with bind()");
exit(1);
}
/*Activar socket com fila de espera de dimensão MAXPENDING*/
if(listen(servSock,MAXPENDING) < 0)
{
perror("Error with listen()");
exit(1);
}
/*Ciclo de processamento (envio/recepção de mensagens)*/
clntLen = sizeof(clntAddr);
if((clntSock = accept(servSock,(struct sockaddr*)&clntAddr,&clntLen)) < 0)//bloqueante
{
perror("Error with accept()");
exit(1);
}
if((recvMsgSize = recv((clntSock),query,sizeof(QUERY),0)) < 0)
{
perror("Error with recv()");
exit(1);
}
// pthread_create(&thread1,0,&HandleTcpClient,(void *)clntSock);
// pthread_join(thread1,0);
HandleTcpClient(query);
close(servSock);
exit(0);
}
client.c
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include "query.h"
#define RCVBUFSIZE 32
int main(int argc, char * argv[])
{
int i;
int sock;
struct sockaddr_in servAddr;
unsigned short servPort;
char * servIP;
QUERY * command;
command = (QUERY *)malloc(sizeof(QUERY));
memset(command,0,sizeof(command));
if(argc!=8)
{
fprintf(stderr,"Usage: %s [<Server IP>] [<Port>] [<Key>][<Description>][<Price>] [<Quantity>][<Localization>] \n",argv[0]);
exit(1);
}
servIP = argv[1];
servPort = atoi(argv[2]);
if((sock = socket(AF_INET,SOCK_STREAM,0)) < 0)//criação do socket do cliente
{
perror("Fim");
exit(1);
}
/* Preenchimento dos dados relativos ao socket criado(do cliente) para passar à função connect -> Quando connect é executado, o servidor vai conferir os dados!*/
memset(&servAddr,0,sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = inet_addr(servIP);
servAddr.sin_port = htons(servPort);
printf("Chegou aqui 1\n");
if(connect(sock,(struct sockaddr*)&servAddr,sizeof(servAddr)) < 0)
{
perror("Error with connect()");
exit(1);
}
/*Ligação estabelecida...receber instruções */
command->codigo_produto = htons(atoi(argv[3]));//chave
command->descricao = argv[4];
command->preco = htonl(atoi(argv[5]));
command->quantidade = htons(atoi(argv[6]));
command->localizacao = argv[7];
//strcpy(command->localizacao,argv[7]);
if(send(sock, command, sizeof(command),0) != sizeof(command))
{
perror("[Client] Data not Sent\n");
exit(1);
}
close(sock);
exit(0);
}
query.h
typedef struct {
int codigo_produto;//chave
char * descricao;
unsigned int preco;
int quantidade;
char * localizacao;
}QUERY;
At the command line I call the client.exe like this:
./client.exe 127.0.0.1 8080 120 descript 1000 10 localiz
...and server.exe...
./server.exe 8080
When i execute this server-client application, the only value that manages to pass from client to server is codigo_produto. I dont understand why.
Sorry for this long post, but im a bit late on this and i need another perspective.
Cheers! :)