国产+高潮+在线,国产 av 仑乱内谢,www国产亚洲精品久久,51国产偷自视频区视频,成人午夜精品网站在线观看

一次收到多組資料封包,如何處理?

flimulus

請(qǐng)問(wèn),若一次收到多組的資料封包,在 dealInput 函數(shù)上如何處理?

例如: 在 dealInput 函數(shù)上預(yù)期收到27byte但實(shí)際已收到87Byte,是否是回傳0,然後在dealProcess 自行使用 Buffer 切割封包,若是這樣,dealInput 的函數(shù)就無(wú)意義了。
請(qǐng)問(wèn)如何處理?

4677 6 0
6個(gè)回答

walkor 打賞

在配置 例如 conf/conf.d/xxx.conf 中 有個(gè) preread_length 字段,這個(gè)字段表明當(dāng)有數(shù)據(jù)到來(lái)時(shí),你不會(huì)全部讀取,而是讀取preread_length長(zhǎng)度。

將preread_length設(shè)置成你預(yù)期讀取的數(shù)據(jù)長(zhǎng)度,一般設(shè)置為你協(xié)議包頭的長(zhǎng)度。例如你的協(xié)議包頭長(zhǎng)度為27byte,則preread_length=27。dealInput在一個(gè)請(qǐng)求數(shù)據(jù)到來(lái)時(shí),會(huì)預(yù)先讀取27字節(jié),一般根據(jù)頭部這27字節(jié)能夠計(jì)算出整體包長(zhǎng),例如整個(gè)包包長(zhǎng)是1027,那么你還差1000byte沒(méi)收到,則dealnput返回1000,那么workerman會(huì)再次等待1000byte數(shù)據(jù)到來(lái)并讀取1000byte

  • 暫無(wú)評(píng)論
flimulus

因?yàn)闇y(cè)試主機(jī)在新加坡,所以封包資料會(huì) Delay,並且同時(shí)收到多筆。

我的問(wèn)題是連續(xù)傳送多筆封包資料,其中最後一筆尚未收完,若是以現(xiàn)在您設(shè)計(jì)的架構(gòu),則無(wú)法準(zhǔn)確處理單獨(dú)的每一筆封包。

我現(xiàn)在的解決方法,是在 dealInput 計(jì)算封包長(zhǎng)度時(shí),若傳回超過(guò)單筆封包長(zhǎng)度時(shí),便傳回負(fù)數(shù),讓dealProcess 能得到完整的封包,剩下的封包等接收完畢後,在下一次傳給dealInput 檢查。

初步修改的程式碼如下:

public function dealInput($recv_str)
 { 
  1. 未達(dá)一個(gè)完整資料
    return  單一筆資料的長(zhǎng)度 - strlen($recv_st); // 正數(shù)
  2. 剛好收到一筆資料
    return 單一筆資料的長(zhǎng)度-strlen($recv_st); // 0
  3. 收到多筆資料(溢收)
    return 單一筆資料的長(zhǎng)度 - strlen($recv_str); //  負(fù)數(shù)
}

//========================================================
public function dealInputBase($connection, $flag, $fd = null)
   {
        $this->currentDealFd = $fd;
        $buffer = stream_socket_recvfrom($connection, $this->recvBuffers);
        // 出錯(cuò)了
        if('' == $buffer && '' == ($buffer = fread($connection, $this->recvBuffers)))
        {
            if(!feof($connection))
            {
                return;
            }            
            // 客戶(hù)端提前斷開(kāi)鏈接
            $this->statusInfo++;
            // 如果該鏈接對(duì)應(yīng)的buffer有數(shù)據(jù),說(shuō)明發(fā)生錯(cuò)誤
            if(!empty($this->recvBuffers))
            {
                $this->statusInfo++;
                $this->notice("CLIENT_CLOSE\nCLIENT_IP:".$this->getRemoteIp()."\nBUFFER:\n");
            }

            // 關(guān)閉鏈接
            $this->closeClient($fd);
            if($this->workerStatus == self::STATUS_SHUTDOWN)
            {
                $this->stop();
            }
            return;
        }        

        $this->recvBuffers .= $buffer;

        // 分拆資料封包
    while(true)
    {       
           $remain_len = $this->dealInput($this->recvBuffers);

          if ($remain_len<=0) 
          {         
            $data = $this->recvBuffers;

            if ($remain_len<0) //  只傳一筆資料至dealProcess
            {           
              $data = substr($data,0,strlen($data)+$remain_len);                
            }

            $this->dealProcess($data);  

            if ($remain_len<0) // 負(fù)數(shù) 再分拆
            {               
              $this->recvBuffers = substr($this->recvBuffers,$remain_len); // 複製新資料               
             }else{
              if($this->isPersistentConnection)
              {                
                 $this->recvBuffers  = array('buf'=>'', 'remain_len'=>$this->prereadLength);                 
              }else{
                // 關(guān)閉鏈接
                if(empty($this->sendBuffers))
                {
                    $this->closeClient($fd);
                }
              }          
              break;    
            }       
      }
      else if(false === $remain_len)
          {
            // 出錯(cuò)
            $this->statusInfo++;
            $this->sendToClient('packet_err:'.$this->recvBuffers);
            $this->notice("PACKET_ERROR\nCLIENT_IP:".$this->getRemoteIp()."\nBUFFER:\n");
            $this->closeClient($fd);
            break;
          }
          else 
          {
            $this->recvBuffers = $remain_len;
            break;
          }                   
    }

        // 檢查是否是關(guān)閉狀態(tài)或者是否到達(dá)請(qǐng)求上限
        if($this->workerStatus == self::STATUS_SHUTDOWN || $this->statusInfo >= $this->maxRequests)
        {
            // 停止服務(wù)
            $this->stop();
            // EXIT_WAIT_TIME秒后退出進(jìn)程
            pcntl_alarm(self::EXIT_WAIT_TIME);
        }
    }

這樣不知有沒(méi)有問(wèn)題?

謝謝。

  • 暫無(wú)評(píng)論
walkor 打賞

在一個(gè)請(qǐng)求開(kāi)始時(shí)dealInput($recv_str) 中的$recv_str長(zhǎng)度不會(huì)超過(guò)你設(shè)定的 preread_length,后面也不會(huì)超過(guò)你在 dealInput($recv_str) return 的長(zhǎng)度,所以不存在收到的$recv_str長(zhǎng)度大于單一資料的長(zhǎng)度。

雖然有可能在服務(wù)端的socket緩沖區(qū)堆積多筆資料,但是workerman還是嚴(yán)格按照 preread_length + dealInput($recv_str) 的return值來(lái)從socket緩沖區(qū)截取數(shù)據(jù),只有當(dāng)前單筆數(shù)據(jù)處理完畢后,才會(huì)去socket緩沖區(qū)按照同樣的規(guī)則截取下一筆數(shù)據(jù)資料。所以只要你的 preread_length 和 dealInput($recv_str) 的return值是正確的,$recv_str不會(huì)超過(guò)單筆資料的長(zhǎng)度。

  • 暫無(wú)評(píng)論
flimulus

可能我設(shè)定錯(cuò)誤,我再試試看。
謝謝您的回答。

  • 暫無(wú)評(píng)論
flimulus

我找到問(wèn)題了,因?yàn)槲沂鞘褂?workerman-chat-master 這個(gè)專(zhuān)案去修改。

而 Gateway.conf 的 preread_length 設(shè)定為 65535 所以才會(huì)出現(xiàn)多筆資料一次傳送,修改為正確值後

就正常的, 謝謝您的回應(yīng)。

  • 暫無(wú)評(píng)論
walkor 打賞

好的,不客氣。

  • 暫無(wú)評(píng)論
年代過(guò)于久遠(yuǎn),無(wú)法發(fā)表回答
??