2013-05-29 25 views
1

我正在创建一个程序,可以通过C++获取包并将其打印到控制台。 我的字符数组设置为1024,如:关于C++中的套接字recv和char []

char* buffer = new char[1024]; 

当我得到一个消息是不完全1024个字符之间,有我的消息,因为数组中的空白空间到底有多少未知字符。我能做什么?

更多的信息(我不知道这是否是有用的)

插座是由Java程序

Socket socket = new Socket("127.0.0.1", 27555); 

BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); 
out.write("I am your client :D"); 
out.flush(); 

发送,服务器是用C++控制台应用程序

char* recvData = new char[1024]; 
recv(socket, recvData, strlen(recvData), 0); 
cout << recvData << endl; 

回答

7

有三个问题与代码:传递给strlen()

  • recvData被unitialised。 strlen()当它找到一个空的终止字符,它可能在缓冲区内或外部时,确定缓冲区的长度。应该将缓冲区的大小减去一个用于终止空字符的大小,作为要读取的最大字节数。
  • recv()的结果未被查询。代码将使用recvData即使recv()失败,这是一个错误。
  • recv()不会终止缓冲区。

保存的recv()的结果,如果没有-1使用它作为一个索引recvData插入空终止字符。

或者,因为这是C++使用std::vector<char>和管理动态内存分配给你(如果动态内存分配真正需要):

std::vector<char> recvData(1025); // Default initializes all elements to 0. 
int result = recv(socket, recvData.data(), recvData.size() - 1); 
if (result != -1) 
{ 
    std::cout << recvData.data() << std::endl; 
} 

记住它只是一个字节流是通过套接字发送的数据,它不会被分成不同的消息。这意味着:

out.write("I am your client :D"); 

可能不会被以recv()单个呼叫读取。同样:

out.write("I am your client :D"); 
out.write("OK"); 

力量通过向recv()单个呼叫读取。如果需要基于消息的处理,则程序员有责任实施协议。

5

strlen计算字节数,直到遇到null('\0')字符。无法保证一个recv调用返回的数据将被终止,因此您需要检查返回的字节数,然后添加您自己的终止符。

char* recvData = new char[1024]; 
int bytes = recv(socket, recvData, 1023, 0); 
if (bytes == -1) { 
    cout << "error on recv" << endl; 
} 
else { 
    recvData[bytes] = '\0';  
    cout << recvData << endl; 
} 
0

这不明显吗? :)

只要首先发送字符串的长度或“正确”终止字符串(通过在字符串结束后发送\0;我猜这是Java在此处未执行的操作)。但是总的来说,无论如何,你应该包括“数据包长度”,因为在写入缓冲区之前可能需要确保有足够的可用空间(在未初始化的数组上使用strlen()通常是一个坏主意)。

1

recvData不是零终止,所以在这种情况下strlen()的结果是不确定的。你必须做如下事情:

int len = 1024; 
char *recvData = new char[len + 1]; 
int lenRead = recv(socket, recvData, len, 0); 
if (lenRead < len) 
    recvData[lenRead] = '\0'; 
else 
    recvData[len] = '\0'; 
cout << recvData << endl;