2013-05-29 26 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;