2016-11-29 70 views
0

我目前正在为Linux编写一个套接字包装器。它基本上是处理TCP套接字的创建,连接,发送,读取和关闭的类的集合。C++套接字只发送前4个字节的数据

在我的套接字类中,除了发送和接收函数外,所有函数都能正常工作。他们不会返回错误;相反,它只发送前四个字节的数据。

我的发送功能:

int Socket::sends(char* buffer){ 

    int bytes; // for number of bytes sent 

    /* First, send the size of buffer */ 
    int datalen = strlen(buffer); // get sizeof buffer 
    int len  = htonl(datalen); // reformat 

    // send the size of the buffer 
    bytes = send(socketfd, (char*)&len, sizeof(len), 0); // send the size 
    if (bytes < 0){ 
     cerr << "Error sending size of buffer to socket" << endl; 
     return 1; 
    } 

    /* Now acutally send the data */ 

    bytes = send(socketfd, buffer, datalen, 0); 
    if (bytes < 0){ 
     cerr << "Error writing buffer to socket" << endl; 
     return 1; 
    } 

    cout << bytes << " written" << endl; 

    return 0; 

} 

其背后的想法是,这将首先发送缓冲区的大小,然后发送实际的缓冲区的缓冲区(char* buffer)。如果遇到一个错误(返回-1)函数通过返回1

现在终止,这里是读法:

int Socket::reads(char* buffer){ 

    int bytes, buflen; // for bytes written and size of buffer 

    /* Read the incoming size */ 
    bytes = recv(socketfd, (char*)&buflen, sizeof(buflen), 0); 
    if (bytes < 0){ 
     cerr << "Error reading size of data" << endl; 
     return 1; 
    } 
    buflen = ntohl(buflen); 

    /* Read the data */ 

    bytes = recv(socketfd, buffer, buflen, 0); 
    if (bytes < 0){ 
     cerr << "Error reading data" << endl; 
     return 1; 
    } 

    return 0; 
} 

在这里,想法是先读取数据的大小,然后将缓冲区设置为该大小并读入。错误时函数返回1(recv返回-1)。

使用方法会是这个样子:

socket.sends("Hello World"); // socket object sends the message 

char* buffer; 
socket.reads(buffer); // reads into the buffer 

然而,当过我使用这些功能,我只收到了前4个字节的数据,其次是陌生的,非ASCII字符。我不知道为什么会发生这种情况。 sendrecv函数中没有遇到错误,函数说明只写入4个字节。有更好的方法来发送或接收数据吗?我忽略了一个非常简单的错误?

感谢您的帮助!

+1

请注意,C和C++是不同的语言。请仅使用相关标签。 – kaylum

+2

你怎么知道有足够的内存分配给读取?示例代码创建一个名为“buffer”的指针,但不会将其指向任何分配的内存。 –

+1

如果您使用的是非阻塞套接字,'recv'可能会读取任意数量的字节(包括0),您需要调用'recv'直到获得所有数据或返回错误。 – alain

回答

4

您正在将未初始化的指针(buffer)传递给您的reads方法,这可能说明它部分工作(未定义的行为)。

,你不应该通过buffer作为参数,因为它不会被修改(和你不知道的大小尚未反正)

另外,你必须用空字符结束,当你收到您的留言它。

我会做这样的:

char *Socket::reads(){ 
    char* buffer; 
    int bytes, buflen; // for bytes written and size of buffer 

    /* Read the incoming size */ 
    bytes = recv(socketfd, (char*)&buflen, sizeof(buflen), 0); 
    if (bytes < 0){ 
     cerr << "Error reading size of data" << endl; 
     return 1; 
    } 
    buflen = ntohl(buflen); 
    buffer = new char[buflen+1]; // +1 for the NUL-terminator 
    /* Read the data */ 

    bytes = recv(socketfd, buffer, buflen, 0); 
    if (bytes < 0){ 
     cerr << "Error reading data" << endl; 
     return 1; 
    } 
    buffer[buflen] = '\0'; // NUL-terminate the string 

    return buffer; 
} 

主:

socket.sends("Hello World"); // socket object sends the message 

char* buffer = socket.reads(); // reads into the buffer 

不要忘记delete []到底缓冲区。

也可以用std::stringstd::vector<char>做是为了避免newdelete

+0

这是个好建议,但是如果OP的'buffer'足够大,就没有UB。它不是未初始化的,它大概是分配的,然后传递给函数。 – alain

+0

你可能是对的。也许我很快回答确定。我肯定是空终止部分。即使缓冲区足够大,如果您没有终止,您也会得到垃圾,因为它没有被发送。 –

+0

当在OP末尾的代码中出现'socket.reads(buffer);'时,''buffer'显然是未初始化的。 –