I'm new to c++ and need help. I use an UDP server to receive structure however i have problem to read it , the client send a structure I call : ChannAccessReq so the structure is send and the server receive it with RECVFROM and I use a general structure by reading the header (H1) of the struct only and then i do a read when a condition is fullfill with a more precise structure (temp2) for the buffer. However the client need to send the message twice , the first time it goes until recvfrom and the second it reach read() (i think) I tried all the day and wonder if its the size of the buffer ?
I think the most sensitive part is in the server with the recvfrom() who have a struct different from the read() just after..
I hope it's clear!
here is the server :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "struct.h"
#include <iostream>
void DieWithError(char *err) {
perror(err);
exit(1);
}
typedef struct IntMsgHeaderType {
uint8_t code ; // Code message7
uint8_t bourrage ; // Octet de bourrage
uint16_t ParamLength; // Longueur eventuel données complémentaires
} HeaderInt;
typedef struct TextMessage //TESTTESTTEST
{
HeaderInt H; // Code message7
};
int main(int argc, char *argv[])
{
int sock; /* Socket */
struct sockaddr_in echoServAddr; /* Local address */
struct sockaddr_in echoClntAddr; /* Client address */
unsigned int cliAddrLen; /* Length of incoming message */
unsigned short echoServPort; /* Server port */
int recvMsgSize; /* Size of received message */
struct TextMessage * temp = (TextMessage *)malloc(sizeof(struct TextMessage));
HeaderInt *H1 =(HeaderInt *)malloc(104+sizeof(HeaderInt));
ChanAccesReq *temp2=(ChanAccesReq *)malloc(sizeof(ChanAccesReq));
if (!argv[1]) {
fprintf(stderr,"no port number provided");
exit(1);
}
echoServPort = atoi(argv[1]); /* First arg: local port */
/* Create socket for sending/receiving datagrams */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
DieWithError("socket() failed");
/* Construct local address structure */
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
echoServAddr.sin_family = AF_INET; /* Internet address family */
echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
echoServAddr.sin_port = htons(echoServPort); /* Local port */
/* Bind to the local address */
if (bind(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
DieWithError("bind() failed");
for (;;) /* Run forever */
{
cliAddrLen = sizeof(echoClntAddr);
int nbrOctet;
if (recvfrom(sock, H1, sizeof(*H1), 0,(struct sockaddr *) &echoClntAddr, &cliAddrLen)>0 && H1->code==1){
//read(sock,H1,sizeof(*H1));
std::cout<<"taille nbrOctet : "<<nbrOctet<<'\n';
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
read(sock, temp2, sizeof(*temp2));
//read(sock,temp2,sizeof(*temp2))>0;
std::cout<<unsigned(temp2->P.linkAddr)<<'\n';
};
}
close(sock);
return 0;
}
and here the client
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "struct.h"
void DieWithError(char *err) {
perror(err);
exit(1);
}
typedef struct {
char transMode ;
uint8_t linkAddr;
} ChanAccessReqParam;
typedef struct {
HeaderInt H;
ChanAccessReqParam P;
} ChanAccesReq ;
int main(int argc, char *argv[])
{
int sock; /* Socket descriptor */
struct sockaddr_in echoServAddr; /* Echo server address */
struct sockaddr_in fromAddr; /* Source address of echo */
unsigned short echoServPort; /* Echo server port */
unsigned int fromSize; /* In-out of address size for recvfrom() */
char *servIP; /* IP address of server */
int structLen; /* Length of string to echo */
int respStringLen; /* Length of received response */
if (!argv[1]) {
fprintf(stderr,"No server IP sepcified at arg 1\n");
exit(1);
}
else if (!argv[2]) {
fprintf(stderr,"No port Number Sepcified at arg 2\n");
exit(2);
}
ChanAccesReq test { 1 ,1,0,'c',15};
servIP = argv[1]; /* First arg: server IP address (dotted quad) */
echoServPort = atoi(argv[2]); /* Use given port, if any */
/* Create a datagram/UDP socket */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
DieWithError("socket() failed");
/* Construct the server address structure */
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
echoServAddr.sin_family = AF_INET; /* Internet addr family */
echoServAddr.sin_addr.s_addr = inet_addr(servIP); /* Server IP address */
echoServAddr.sin_port = htons(echoServPort); /* Server port */
int tempint = 0;
tempint = sendto(sock, (ChanAccesInd*)&test, 10+(sizeof(test)), 0, (struct sockaddr *)
&echoServAddr, sizeof(echoServAddr));
if (tempint == -1 ) {
printf("Sent struct size: %d\n", tempint);
DieWithError("sendto() sent a different number of bytes than expected\n");
}
close(sock);
exit(0);
}
Thank you for your help
you can use a flag on recvfrom like "PEEK" see the modified code here :
recvfrom(sock, HeaderStruct, sizeof(*HeaderStruct), MSG_PEEK,(struct sockaddr *) &echoClntAddr, &cliAddrLen);
and the full code here
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "struct.h"
#include <iostream>
void GesCanSrvRecvMsg(){
int sock; // Socket
struct sockaddr_in echoServAddr; // Adresse local
struct sockaddr_in echoClntAddr; // Adresse Client
unsigned int cliAddrLen; // Longeur des messages entrant
unsigned short echoServPort; // Port Serveur
unsigned recvMsgSize; // Taille message reçu
//Creation allocation memoire necessaire pour recevoir les structures
HeaderInt *HeaderStruct=(HeaderInt *)malloc(sizeof(HeaderInt));
ChanAccesReq *ChanReqStruct=(ChanAccesReq *)malloc(sizeof(ChanReqStruct));
TransTimeReq *TransTReqStruct=(TransTimeReq *)malloc(sizeof(TransTReqStruct));
TransCancelReq *TransCReqStruct=(TransCancelReq *)malloc(sizeof(TransCReqStruct));
//Port definie a 13000
echoServPort = atoi("13000"); //Premier argument port local
//Creation socket
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
Error("socket() failed");
//Construct local address structure
memset(&echoServAddr, 0, sizeof(echoServAddr));
echoServAddr.sin_family = AF_INET;
echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY);
echoServAddr.sin_port = htons(echoServPort);
//Bind a ladresse
if (bind(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
Error("bind() failed");
while(1) //Boucle infinie
{
cliAddrLen = sizeof(echoClntAddr);
HeaderStruct->code=0;
/*Attente des messages en ne regarde que l'entete Header
Flag -> MSG_PEEK pour eviter un double envoie du client*/
recvfrom(sock, HeaderStruct, sizeof(*HeaderStruct), MSG_PEEK,(struct sockaddr *) &echoClntAddr, &cliAddrLen);
std::cout<<"coucou"<<'\n';
char* subscIPAddr=inet_ntoa(echoClntAddr.sin_addr); // adresse iP Client
if (unsigned(HeaderStruct->code)==ChanAccessReqc){ //Si code == ChanAccessReqC (1)
recv(sock,ChanReqStruct,sizeof(*ChanReqStruct),0);
CSMAChnAccessLstReq.push_back(*ChanReqStruct); //Placement dans liste partagée avec GesCanSlot
}
else if (unsigned(HeaderStruct->code==TransTimeReqc)){ //Si code == TransTimeReqc (3)
recv(sock,TransTReqStruct,sizeof(*TransTReqStruct),0);
CSMATimeTransmLstReq.push_back(*TransTReqStruct);
}
else if (unsigned(HeaderStruct->code==TransCancelReqc)){ //Si code == TransCancelReqc (3)
recv(sock,TransCReqStruct,sizeof(*TransCReqStruct),0);
TransacCancelLst.push_back(*TransCReqStruct);
}
else {
Error("Error");
}
}
close(sock);
};
int main(int argc, char *argv[])
{
GesCanSrvRecvMsg();
return 0;
}