c++ 如何从UDP客户端向服务器发送一个结构体?

m0rkklqb  于 2022-12-15  发布在  其他
关注(0)|答案(1)|浏览(194)

我在从UDP客户端向UDP服务器发送一个数据结构时遇到了一些问题。我不确定到底是什么问题。我有一个源文件,负责设置UDP客户端并定义发送数据的函数:
UDPClient.cpp

#include "UDPClient.h"

UDPClient::UDPClient(unsigned short port) {

    // UDP Client sends messages to UDP server on this port.
    this->port = port;

    // Create UDP socket file descriptor.
    // int socket(int domain, int type, int protocol);
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        std::cerr << "ERROR: Socket creation failed. socket() system call returned an error." << std::endl;
        exit(EXIT_FAILURE);
    }

    // Zero memory of serv_addr struct.
    memset(&serv_addr, 0, sizeof(serv_addr));

    // Configure server address structure.
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(port);
}

void UDPClient::send(const char* bytes) {
    // ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
    sendto(sockfd, bytes, strlen(bytes), MSG_CONFIRM, (const sockaddr*)&serv_addr, sizeof(serv_addr));
    std::cout << "Message Sent." << std::endl;
}

下面是头文件:
UDPClient.h

#ifndef UDPCLIENT_H
#define UDPCLIENT_H

#include <iostream>
#include <cstring>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>

class UDPClient
{
public:
    UDPClient(unsigned short);
    void send(const char*);
private:
    unsigned short port;
    int sockfd;
    sockaddr_in serv_addr;
};

#endif

然后,我让源文件负责声明一个struct,并使用reinterpret_cast()函数将其更改为字节字符串来发送该struct的数据。
sendData.cpp

#include "UDPClient.h"

struct myStruct {
    int a;
    double b;
    float c;
};

int main() {
    unsigned short port = 22842;
    UDPClient client(port);

    myStruct data;
    data.a = 1;
    data.b = 2.0;
    data.c = 3.0;

    const char* dataInBytes = reinterpret_cast<char*>(&data);
    client.send(dataInBytes);
}

我还有一个非常类似的设置,用于设置UDP服务器并定义从其接收数据的函数。
UDPServer.cpp

#include "UDPServer.h"

UDPServer::UDPServer(unsigned short port) {
    
    // UDP Server binds to an address on this port.
    this->port = port;
    
    // Create UDP socket file descriptor.
    // socket(int domain, int type, int protocol);
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        std::cerr << "ERROR: Socket creation failed. socket() system call returned an error." << std::endl;
        exit(EXIT_FAILURE);
    }

    // Zero memory of serv_addr struct.
    memset(&serv_addr, 0, sizeof(serv_addr));

    // Configure server address structure.
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(port);

    // Bind the socket to the server address.
    // int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    if (bind(sockfd, (sockaddr*) &serv_addr, sizeof(serv_addr)) < 0) {
        std::cerr << "ERROR: Binding socket failed. bind() system call returned an error." << std::endl;
        exit(EXIT_FAILURE);
    }

    cli_len = sizeof(cli_addr);
}

char* UDPServer::receive() {
    // ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
    int n = recvfrom(sockfd, (char*) buffer, MAXLINE, MSG_CONFIRM, (sockaddr*) &cli_addr, &cli_len);
    return buffer;  
}

下面是头文件:
UDPServer.h

#ifndef UDPSERVER_H
#define UDPSERVER_H

#include <iostream>
#include <cstring>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>

#define MAXLINE 1024

class UDPServer
{
public:
    UDPServer(unsigned short);
    char* receive();
private:
    unsigned short port;
    int sockfd;
    sockaddr_in serv_addr;
    sockaddr_in cli_addr;
    socklen_t cli_len;
    char buffer[MAXLINE];
};

#endif

现在,我尝试通过实现UDP服务器并将它接收到的字节串的内存复制回一个结构体来接收结构体中包含的数据:
receiveData.cpp

#include "UDPServer.h"

struct myStruct {
    int a;
    double b;
    float c;
};

int main() {
    unsigned short port = 22842;
    UDPServer server(port);

    myStruct data;

    char* bytes = server.receive();

    memcpy(&data, bytes, sizeof(data));

    std::cout << "int a: " << data.a << std::endl;
    std::cout << "double b: " << data.b << std::endl;
    std::cout << "float c: " << data.c << std::endl;
}

预期输出为:

int a: 1
double b: 2.0
float c: 3.0

但我得到的却是

int a: 1
double b: 0
float c: 0

为什么结构数据没有被正确传递?我在这里做错了什么?任何帮助都是感激的。

bvhaajcl

bvhaajcl1#

struct不是以null结尾的字符串,不能使用strlen()获取其长度。需要使用sizeof data,并将其作为参数传递给send()

void UDPClient::send(const char* bytes, size_t len) {
    // ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
    sendto(sockfd, bytes, len, MSG_CONFIRM, (const sockaddr*)&serv_addr, sizeof(serv_addr));
    std::cout << "Message Sent." << std::endl;
}
int main() {
    unsigned short port = 22842;
    UDPClient client(port);

    myStruct data;
    data.a = 1;
    data.b = 2.0;
    data.c = 3.0;

    const char* dataInBytes = reinterpret_cast<char*>(&data);
    client.send(dataInBytes, sizeof data);
}

相关问题