如何解决发送结构UDP Socket的问题
我是 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,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),(struct sockaddr *) &echoClntAddr,&cliAddrLen)>0 && H1->code==1){
//read(sock,sizeof(*H1));
std::cout<<"taille nbroctet : "<<nbroctet<<'\n';
memset(&echoServAddr,sizeof(echoServAddr)); /* Zero out structure */
read(sock,temp2,sizeof(*temp2));
//read(sock,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,'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,IPPROTO_UDP)) < 0)
DieWithError("socket() Failed");
/* Construct the server address structure */
memset(&echoServAddr,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)),(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);
}
感谢您的帮助
解决方法
您可以在 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,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,&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;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。