在C / C ++中通过套接字传输整数数组

时间:2016-09-07 20:29:44

标签: c++ sockets

This回答显示了在c / c ++中通过套接字发送和接收整数的方法。基于我写的以下两个函数,sendKInt和receiveKInt发送和接收K个整数。但它不能正常工作。也许我的指针算术是错误的,但我找不到错误。请帮忙,我是c ++的新手。另请参阅sendTill和receiveTill函数。

bool sendKInt(int fd, int num[], int k){ // returns true on success
    int32_t conv[k];
    char *data;
    for (int i=0; i<k; i++){
        conv[i] = htonl(num[i]);
        char *data = (char*)conv;
    }
    return sendTill(sizeof(int32_t)*k, fd, data);
}

bool receiveKInt(int fd, int *num, int k){ // returns true on success
    int32_t ret[k];
    int toReturn = receiveTill(sizeof(int32_t)*k,fd,(char*)ret);
    for (int i=0; i<k; i++){
        num[i] = ntohl(ret[i]);
    }
    return toReturn;
}

bool sendTill(int size, int fd, char* dataU){ // dataU - dataUser pointer is NULL then create your own buffer and send random thing // returns true on successs
    char *data;
    int left = size;
    int rc;
    if(dataU == NULL){
        data = (char*)malloc(size);
    }else{
        data = dataU;
    }
    while (left) {
        rc = write(fd, data + size - left, left);
        if (rc < 0){
            cout <<"-1 in sendTill \n";
            return false;
        }
        left -= rc;
    }
    return true;
}

bool receiveTill(int size, int fd, char* data){ // just give a char pointer after allocating size // returns true on success
    int ret;
    int left = size;
    while (left) {
        ret = read(fd, data + size - left, left);
        if (ret < 0){
            cout <<"-1 in receiveTill \n";
            return false;
        }
        left -= ret;
    }
    return true;
}

4 个答案:

答案 0 :(得分:4)

char *data;

不同
char *data = (char*)conv;

你有两个data个,一个在for循环中被分配,一个在外面不是这样

return sendTill(sizeof(int32_t)*k, fd, data);

结束发送外部未初始化的data。 Crom只知道会发生什么。

幸运的是,没有必要做

char *data = (char*)conv;

几百次,所以

return sendTill(sizeof(int32_t)*k, fd, (char*)conv);

看起来会起作用。可悲的是,它不会在C ++中。

int32_t conv[k];

是无效的C ++。 k在编译时是未知的,因此这需要非标准的可变长度数组编译器扩展。一些编译器将允许这种语法,但它有一些缺点(常见的实现很容易超出堆栈,并且对sizeof的行为非常混乱)并且不会在所有编译器上编译。如果您需要将代码移植到其他平台或将代码提交给将评估代码并使用的代码(例如,Visual Studio),那真的很糟糕。

C ++ 11有std::vector::data所以你可以

bool sendKInt(int fd, int num[], int k){ // returns true on success
    std::vector<int32_t> conv(k);
    for (int i=0; i<k; i++){
        conv[i] = htonl(num[i]);
    }
    return sendTill(sizeof(int32_t)*k, fd, (char *)conv.data());
}

答案 1 :(得分:2)

你声明了两个data个变量,第二个隐藏了第一个变量。

bool sendKInt(int fd, int num[], int k){ // returns true on success
    int32_t conv[k];

    // First "data", points to undefined value
    char *data;
    for (int i=0; i<k; i++){
        conv[i] = htonl(num[i]);

        // local data, points to conv
        // HIDES the first data declared above
        char *data = (char*)conv;
    }

    // uses the only "data" in scope, which points to undefined location
    return sendTill(sizeof(int32_t)*k, fd, data);
}

答案 2 :(得分:2)

为什么它不起作用

目前尚不清楚您是否打算sendKInt()

  • 根据您在通话中使用的参数sendTill()建议,通过sizeof(int32_t)*k发送所有数据
  • 逐个发送数据,因为您的转换循环只转换单个项目

sendKInt()循环中,你有两个非常大的错误:

  • 在循环中声明了一个bloc变量char *data。此变量使用相同的名称隐藏外部变量,并在退出循环后立即丢失其值。
  • 退出循环时,使用仍未初始化的外部数据变量调用sendTill()。这是未定义的行为保证!
  • 请注意,即使您不会隐藏数据变量,它也不会起作用,因为您将转换值(即要传输的整数)转换为指向字符的指针(例如,如果整数是0,你将使用null poitner)。所以你会尝试发送一个流氓指针,所以肯定不是你所期望的价值。

如何解决

我假设C使用malloc()

bool sendKInt(int fd, int num[], int k){ // returns true on success
    int32_t *data = calloc (sizeof(int32_t), k);  // allocate for everything
    if (data==NULL)                            // allocation failure
        return 0;                               
    for (int i=0; i<k; i++){                   // convert everything 
        data[i] = htonl(num[i]);
    }
    bool rc = sendTill(sizeof(int32_t)*k, fd, (char*)data);
    free(data);                               // malloc=> free (or you'll leak memory) 
    return rc;                            // now that memory is freed, return the result
}

请注意,您必须根据此新逻辑查看其余代码。不要忘记释放在函数中分配的内存,以避免内存泄漏。

答案 3 :(得分:0)

一个很好的代码:

bool sendKInt(int fd, int num[], int k){ // returns true on success
    std::vector<int32_t> conv(k);
    for (int i=0; i<k; i++){
        conv[i] = htonl(num[i]);
    }
    return sendTill(sizeof(int32_t)*k, fd, (char *)conv.data());
}

bool receiveKInt(int fd, int *num, int k){ // returns true on success
    int32_t *ret = (int32_t*)calloc (sizeof(int32_t), k);
    bool toReturn = receiveTill(sizeof(int32_t)*k,fd,(char*)ret);
    for (int i=0; i<k; i++){
        num[i] = ntohl(ret[i]);
    }
    free(ret);
    return toReturn;
}

bool sendTill(int size, int fd, char* dataU){ // dataU - dataUser pointer is NULL then create your own buffer and send random thing // returns true on successs
    char *data;
    int left = size;
    int rc;
    if(dataU == NULL){
        data = (char*)malloc(size);
    }else{
        data = dataU;
    }
    while (left) {
        rc = write(fd, data + size - left, left);
        if (rc < 0){
            cout <<"-1 in sendTill \n";
            return false;
        }
        left -= rc;
    }
    return true;
}

bool receiveTill(int size, int fd, char* data){ // just give a char pointer after allocating size // returns true on success
    int ret;
    int left = size;
    while (left) {
        ret = read(fd, data + size - left, left);
        if (ret < 0){
            cout <<"-1 in receiveTill \n";
            return false;
        }
        left -= ret;
    }
    return true;
}