我在SO上看过类似的问题,但没有回答我的问题。 在这里,我试图发送和recv字符串:
我发送std :: string:
if( (bytecount=send(hsock, input_string.c_str(), input_string.length(),0))== -1)
这可以正确接收吗?
if ((bytecount = recv(*csock, rcv.c_str(), rcv.length(), 0)) == -1)
我收到错误:
错误:在recv行上从'const void *'无效转换为'void *'[-fpermissive]`!
答案 0 :(得分:11)
不,不能。 c_str()会返回const char*
。这意味着您无法覆盖指针的内容。
如果要接收数据,则必须创建缓冲区,例如使用std::vector
然后使用它来创建std::string
。
// create the buffer with space for the data
const unsigned int MAX_BUF_LENGTH = 4096;
std::vector<char> buffer(MAX_BUF_LENGTH);
std::string rcv;
int bytesReceived = 0;
do {
bytesReceived = recv(*csock, &buffer[0], buffer.size(), 0);
// append string from buffer.
if ( bytesReceived == -1 ) {
// error
} else {
rcv.append( buffer.cbegin(), buffer.cend() );
}
} while ( bytesReceived == MAX_BUF_LENGTH );
// At this point we have the available data (which may not be a complete
// application level message).
上面的代码一次会收到4096个字节。如果发送的数据超过4K,它将继续循环并将数据附加到recv
,直到没有更多数据。
另请注意使用&buffer[0]
代替buffer.data()
。获取第一个元素的地址是访问非const指针并避免未定义行为的方法。
答案 1 :(得分:8)
最好的方法是首先以固定格式发送字符串数据的长度(例如,网络字节顺序为uint32_t
)。然后接收器可以先读取它,并在接收到之后发送的序列化消息之前分配适当大小的缓冲区。
sd
和csd
已经存在套接字描述符。
<强> Sender.cpp 强>
std::string dataToSend = "Hello World! This is a string of any length ...";
uint32_t dataLength = htonl(dataToSend.size()); // Ensure network byte order
// when sending the data length
send(sd,&dataLength ,sizeof(uint32_t) ,MSG_CONFIRM); // Send the data length
send(sd,dataToSend.c_str(),dataToSend.size(),MSG_CONFIRM); // Send the string
// data
<强> Receiver.cpp 强>
uint32_t dataLength;
recv(csd,&rcvDataLength,sizeof(uint32_t),0); // Receive the message length
dataLength = ntohl(dataLength ); // Ensure host system byte order
std::vector<uint8_t> rcvBuf; // Allocate a receive buffer
rcvBuf.resize(dataLength,0x00); // with the necessary size
recv(csd,&(rcvBuf[0]),dataLength,0); // Receive the string data
std::string receivedString; // assign buffered data to a
receivedString.assign(&(rcvBuf[0]),rcvBuf.size()); // string
优点是。你不必乱用多个缓冲读取并复制到接收到的字符串。此外,您将在接收方知道发送的数据何时最终完成。
缺点是,在首先发送长度时,你会引入一种'协议'。
答案 2 :(得分:6)
不,std::string::c_str()
返回const char*
,这意味着它是只读的。在recv
成功返回后,您可以分配本地缓冲区并从本地缓冲区创建字符串对象。
您需要告诉recv
函数读取特定长度的数据,例如,您希望每次读取512个字节:
#define DEFAULT_BUFLEN 512
char recvbuf[DEFAULT_BUFLEN];
recv(*csock, recvbuf, DEFAULT_BUFLEN, 0);
答案 3 :(得分:0)
在recv线上
error: invalid conversion from ‘const void*’ to ‘void*’ [-fpermissive]
!
拨打这个特定问题,你写了( sans if
声明):
bytecount = recv(*csock, rcv.c_str(), rcv.length(), 0)
rcv.c_str()
检索const char*
指针。 const char*
被强制转移到const void*
。我知道获取非const指针并避免未定义行为的唯一方法是获取std::string
或std::vector
中的第一个元素的地址:
bytecount = recv(*csock, &rcv[0], rcv.length(), 0)
获取类似的非const指针仅对提供连续内存的STL容器有效。该技巧不适用于map
,multimap
或其他关联容器。
@πάντα-ῥεῖ是唯一回答它的答案,但他没有强调这一点。