2011-11-25 159 views
0

我正面臨一個奇怪的問題。使用PHP作爲C++服務器的套接字客戶端

我寫了一個C++中的小型服務器,它以二進制格式將對象存儲在一個文件中。

我用telnet成功測試過它。

telnet 127.0.0.1 1234 
Trying 127.0.0.1... 
Connected to 127.0.0.1. 
Escape character is '^]'. 
store 1 1 5 1 
store 1 1 5 2 

服務器上的輸出是現在

Command : store 1 1 5 1 
Command : store 1 1 5 2 

因爲我們要使用PHP來存儲這些信息,我寫了一個小PHP腳本,將派遣10個命令到我們的服務器。

<?php 

    $socket = socket_create(AF_INET,SOCK_STREAM,0); 
    socket_connect($socket,"127.0.0.1",1234); 

    for($i = 0;$i < 10;$i++){ 

     $command = "store 1 $i 5 1\r\n"; 

     echo $command; 

     socket_write($socket,$command,strlen($command)); 

    } 

    socket_close($socket); 

?> 

的問題是,來自服務器的輸出是現在:

Command : store 1 0 5 1store 1 1 5 1store 1 2 5 1store 1 3 5 1store 1 4 5 1store 1 5 5 1store 1 6 5 1store 1 7 5 1store 1 8 5 1store 1 9 5 1 

的\ r \ n不認可。在四處搜尋後,我發現通過在socket_write函數後添加一個usleep(10000),它實際上可以工作。

我試圖避免使用此解決方案,所以我要提問:

爲什麼usleep修復它? 如何在不休眠的情況下做到這一點?

感謝您的閱讀!

回答

0

我們將不得不看你的C++服務器,但我懷疑你是在那裏錯誤地解析數據。

TCP是一種流協議,在協議中,數據包中的數據沒有邊界。所以當你發送多個「存儲」命令時,它們可能都出現在同一個TCP數據包中。那麼當你撥打recv()時,你可能會得到多個「商店」。但是,由於時間安排以及telnet可能將每行發送到自己的數據包這一事實,每個撥打recv()的電話都可能檢索到單個「存儲」命令。

當你把usleep放入時,你實際上是在延遲排隊更多的數據,而TCP放棄了等待,並且把數據包中的「存儲」全部發送到它自己的地方。

在你的服務器,你必須

  1. 期待從recv()檢索多個「商店」 S,
  2. 期待一個單一的「店」在多個recv()電話進行分割。

usleep是一個黑客,可能並不總是工作。

相關問題