通过套接字发送和接收字符串的子功能

时间:2014-12-06 08:44:47

标签: c++ c sockets unix client-server

我假设对于只有1个字节(char)的消息,我将直接使用read()和write()。

对于那些尺寸大于>的消息1个字节,我使用两个子函数来读取和写入套接字。

例如,我让服务器构造一个名为strcities(城市列表)的字符串并将其打印出来 - >没什么奇怪的然后将此字符串的字节数发送给客户端,然后发送实际的字符串。

客户端将首先读取字节数,然后读取实际的城市列表。

出于某种原因,我的代码有时会起作用,有时甚至不起作用。如果它有效,它还打印出一些额外的字符,我不知道它们来自哪里。如果它没有,它会挂起并永远在客户端等待,而服务器返回到循环的顶部并等待来自客户端的下一个命令。您能否请看下面的代码,让我知道我哪里做错了?

Attempt_read

string attempt_read(int rbytes) { // rbytes = number of bytes of message to be read
    int count1, bytes_read;   
    char buffer[rbytes+1];
    bool notdone = true;   

    count1 = read(sd, buffer, rbytes); 

    while (notdone) {
        if (count1 == -1){
            perror("Error on write call");
            exit(1);
        }  
        else if (count1 < rbytes) {
            rbytes = rbytes - count1; // update remaining bytes to be read         
            count1 = read(sd, buffer, rbytes);
        }
        else {notdone = false;}
    }     // end while
    string returnme;
    returnme = string(buffer);
    return returnme;
}

Attempt_write

void attempt_write(string input1, int wbytes) { // wbytes = number of bytes of message 
    int count1;
    bool notdone = true; 

    count1 = write(sd, input1.c_str(), wbytes);

    while (notdone) {
        if (count1 == -1){
           perror("Error on write call");
           exit(1);
        }
        else if (count1 < wbytes) {    
           wbytes = wbytes - count1; 
           count1 = write(sd, input1.c_str(), wbytes);     
        }        
        else {notdone = false;}
    } // end while  
    return;  
} 

1 个答案:

答案 0 :(得分:1)

1)字符串类有一个方法size(),它将返回字符串的长度,因此实际上你不需要第二个attempt_write参数。

2)您可以在消息之前传输消息长度,或者如果您只发送ASCII字符串,则可以在之后传输终止0。由于您的连接可以随时终止,因此最好在发送字符串之前发送确切的长度,以便您的客户知道会发生什么。

3)你使用什么编译器,允许char缓冲区[rbytes + 1]; ?标准的c ++需要char buffer = new char [rbytes + 1];并相应删除以避免内存泄漏。

4)在您的代码中,第二个读取函数调用使用相同的缓冲区而不调整长度,因此您实际上会覆盖已接收的数据,并且只有在第一个函数调用中接收到所有数据时该函数才会起作用。写功能也是如此

我会建议这样的事情:

void data_read(unsigned char * buffer, int size) {
    int readed, total = 0;

    do { 
    readed = read(sd, buffer + total, size - total);
    if (-1 == writted) {
        perror("Error on read call");
            exit(1);
        }

    total += readed;
    } while (total < size); 
}

string attempt_read() {  
    int size = 0;   
    data_read((unsigned char *) &size, sizeof(int));

    string output(size, (char) 0x0);

    data_read((unsigned char *) output.c_str(), size);

    return output;
} 

void data_write(unsigned char * buffer, int size) {
    int writted, total = 0;

    do { 
    writted = write(sd, buffer + total, size - total);
    if (-1 == writted) {
        perror("Error on write call");
            exit(1);
        }

    total += writted;
    } while (total < size); 
}

void attempt_write(string input) {  
    int size = input.size();    
    data_write((unsigned char *) &size, sizeof(int));
    data_write((unsigned char *) input.c_str(), size);
}