2014-02-05 59 views
4

我试图向服务器发送一些长度前缀数据,我已经尝试使用其他人在堆栈溢出时发布的代码和解决方案。仍然在寻找如何使用TCP实际工作。因为我不太了解(关于网络编程,但我知道理论概念)。我正在写我到目前为止所尝试的内容。基于此,我有一些问题。C++中的TCP Socket上的可变长度消息

由于我们在客户端使用Char Buffer[200] = "This is data"发送(使用send()函数)字符串和字符型数据到服务器(使用recv()函数接收)。直到这里它可以,但如果我需要发送一些可变长度的消息与他们的长度信息呢? ,我如何将长度信息编码到消息中?

for example: 0C  54 68 69 73 20 69 73 20 64 61 74 61  07 46 72 6f 6d 20 6d 65 
      (length) T h i s i s  d a t a (length) F r o m  m e 


How can i interpret these two message seperately from tcp stream at the sever side ? 

我不知道长度信息可以如何发送separetly?或者如果有人能够理解我的测试用例(在编辑中给出)来验证字符串的长度信息。

编辑:看起来没问题,但我只需要验证一下前缀长度。我发送20个字节(“这是我的数据”)到服务器。我收到的长度大小是4字节(我不知道里面是什么,我需要验证我收到的长度的4个字节是否包含0000 0000 0000 0000 0000 00000 0001 0100)。就是这样,所以我认为通过将长度信息移位2位来验证它的方式应该看起来像(我收到的长度为4个字节包含0000 0000 0000 0000 0000 00000 0000 0101),在这种情况下,我应该只有5个字符即“这个”。你知道我怎么能在服务器端验证这一点?

客户端代码

int bytesSent; 
int bytesRecv = SOCKET_ERROR; 
char sendbuf[200] = "This is data From me"; 

int nBytes = 200, nLeft, idx; 
nLeft = nBytes; 
idx = 0; 
uint32_t varSize = strlen (sendbuf); 
bytesSent = send(ConnectSocket,(char*)&varSize, 4, 0); 
assert (bytesSent == sizeof (uint32_t)); 
std::cout<<"length information is in:"<<bytesSent<<"bytes"<<std::endl; 
// code to make sure all data has been sent 
    while (nLeft > 0) 
{ 
    bytesSent = send(ConnectSocket, &sendbuf[idx], nLeft, 0); 
    if (bytesSent == SOCKET_ERROR) 
    { 
     std::cerr<<"send() error: " << WSAGetLastError() <<std::endl; 
     break; 
    } 
    nLeft -= bytesSent; 
    idx += bytesSent; 
} 
bytesSent = send(ConnectSocket, sendbuf, strlen(sendbuf), 0); 
printf("Client: Bytes sent: %ld\n", bytesSent); 

服务器代码

 uint32_t nlength; 
int length_received = recv(m_socket,(char*)&nlength, 4, 0); 
char *recvbuf = new char[nlength]; 
int byte_recived = recv(m_socket, recvbuf, nlength, 0); 

感谢

+0

我想你将不得不发布一些代码 - 不用看代码就不太可能获得帮助。 – suspectus

+0

@suspectus它在那里,请参阅编辑。 – User

+0

[Here](http://stackoverflow.com/a/6946109/412080)是对类似问题的回答。 –

回答

5

如果您需要发送可变长度的数据,你需要在之前发送的数据的长度数据本身。

在您的代码段以上,则出现在做相反:

while (nLeft > 0) 
{ 
    bytesSent = send(ConnectSocket, &sendbuf[idx], nLeft, 0); 
    // [...] 
} 
bytesSent = send(ConnectSocket, sendbuf, strlen(sendbuf), 0); 

在这里,你第一发送字符串,然后长度。客户如何能够解释这一点?到达长度的时候,他们已经把绳子从插座上拔下来了。

相反,先发的长度,并确保你明确的关于大小字段的大小:

const uint32_t varSize = strlen (sendbuf); 
bytesSent = send(ConnectSocket, &varSize, sizeof (varSize), 0); 
assert (bytesSent == sizeof (uint32_t)); 
while (nLeft > 0) 
{ 
    bytesSent = send(ConnectSocket, &sendbuf[idx], nLeft, 0); 
    // [...] 
} 

您也可以考虑不是在所有发送可变长度的数据。一般来说,固定宽度的二进制协议在接收端更容易解析。你总是可以在一个固定宽度的字段(比如说20个字符)中发送字符串数据,并用空格或\0来填充。这确实会浪费电线上的一些空间,至少在理论上是如此。如果您对固定宽度字段的大小以及您发送的内容很敏感,那么在许多情况下,您可以在这个空间内节省成本。

+0

这似乎没关系,但我只需要验证一下前缀长度。我发送20个字节(“这是我的数据”)到服务器。我收到的长度大小是4个字节(我不知道里面是什么,我需要验证'我收到的长度为4个字节是否包含0000 0000 0000 0000 0000 00000 0001 0100')。这就是它,所以我认为通过将长度信息移位2位来验证它的方式现在应该看起来像(我收到的长度为4个字节包含0000 0000 0000 0000 0000 00000 0000 0101),在这种情况下,我应该只能得到5个字符,即“This”。你知道我怎么能在服务器端验证这一点? – User

+0

请参阅编辑我的问题帖子!也许你会明白我的意思。 – User

+0

@ user3232405:对不起,我没有得到你要的东西。你能澄清一下吗? –