发送结构UDP Socket的问题

时间:2021-04-08 17:27:53

标签: c sockets udp sendto recvfrom

我是 C++ 新手,需要帮助。 我使用 UDP 服务器来接收结构,但是我在读取它时遇到问题,客户端发送一个我调用的结构:ChannAccessReq 所以发送结构,服务器用 RECVFROM 接收它,我使用通用结构通过仅读取结构的标头(H1),然后在条件满足时使用更精确的缓冲区结构(temp2)进行读取。 但是客户端需要发送两次消息,第一次发送到 recvfrom ,第二次发送到 read() (我认为)我尝试了一整天,想知道它的缓冲区大小?

我认为最敏感的部分是在带有 recvfrom() 的服务器中,它的结构与之后的 read() 不同..

我希望清楚!

这里是服务器:

#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;
  }

这里是客户

#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);
}

感谢您的帮助

1 个答案:

答案 0 :(得分:1)

您可以在 recvfrom 上使用标志,例如“PEEK”,请在此处查看修改后的代码:

 recvfrom(sock, HeaderStruct, sizeof(*HeaderStruct), MSG_PEEK,(struct sockaddr *) &echoClntAddr, &cliAddrLen);

和这里的完整代码

#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;
  }

相关问题