2010-02-15 46 views
4

沒有收到我正在開發一個異步接受TCP連接(BeginAccept/EndAccept)和數據(BeginReceive/EndReceive)的服務器應用程序。協議要求在EOM字符被發現之前發送ACK,然後它將發送下一條消息。接受和接收正在工作,但發送應用程序未收到ACK(同步發送)。Windows套接字。發送數據直到socket.Close

private void _receiveTransfer(IAsyncResult result) 
    { 
     SocketState state = result.AsyncState as SocketState; 
     int bytesReceived = state.Socket.EndReceive(result); 

     if (bytesReceived == 0) 
     { 
      state.Socket.Close(); 
      return; 
     } 

     state.Offset += bytesReceived; 
     state.Stream.Write(state.Buffer, 0, bytesReceived); 

     if (state.Buffer[bytesReceived - 1] == 13) 
     { 
      // process message 
      Messages.IMessage message = null; 
      try 
      { 
       var value = state.Stream.ToArray(); 

       // do some work 
       var completed = true; 

       if (completed) 
       { 
        // send positive ACK 
        var ackMessage = string.Format(ack, message.TimeStamp.ToString("yyyyMMddhhmm"), message.MessageType, message.Id, "AA", message.Id); 
        var buffer = ASCIIEncoding.ASCII.GetBytes(ackMessage); 
        int bytesSent = state.Socket.Send(buffer, 0, buffer.Length, SocketFlags.None); 
       } 
       else 
       { 
        // send rejected ACK 
        var ackMessage = string.Format(ack, message.TimeStamp.ToString("yyyyMMddhhmm"), message.MessageType, message.Id, "AR", message.Id); 
        state.Socket.Send(ASCIIEncoding.ASCII.GetBytes(ackMessage)); 
       } 
      } 
      catch (Exception e) 
      { 
       // log exception 


       // send error ACK 
       if (message != null) 
       { 
        var ackMessage = string.Format(ack, DateTime.Now.ToString("yyyyMMddhhmm"), message.MessageType, message.Id, "AE", message.Id); 
        state.Socket.Send(ASCIIEncoding.ASCII.GetBytes(ackMessage)); 
       } 
      } 
     } 

     state.Socket.BeginReceive(state.Buffer, 0, state.Buffer.Length, SocketFlags.None, new AsyncCallback(_receiveTransfer), state); 
    } 

state.Socket.Send返回正確的字節數,但直到套接字處置後纔會收到數據。

建議表示讚賞。

+0

是否有'Flush'功能?我猜猜套接字數據被緩衝,等待更多的數據... –

+1

string.Format()調用看起來很奇怪。但我懷疑真正的問題是在電線的另一端。 –

回答

0

你給它多久了?網絡堆棧可以緩衝,並且可以延遲傳輸。從MSDN

爲了提高網絡效率,直到傳出數據的顯著 量收集的 底層系統可能延遲 傳輸。 發送 方法的成功完成意味着基本的 系統有空間緩衝您的網絡發送的 數據。

您可能想使用IOControl方法嘗試刷新。

編輯

實際上,平齊的IOControl會殺死緩衝區。你可能想看看Two Generals Problem看看你的協議是否會有一些固有的問題。

2
  • 你不應該做任何異步完成例程的同步。在負載下,您最終可能會劫持線程池中的所有IO完成線程,嚴重影響性能,直至幷包含完整的IO死鎖。所以不要從異步回調中同步發送ACK。
  • 使用前導碼的協議和格式比使用終止符的協議和格式更容易管理。 IE瀏覽器。在固定大小的消息頭中寫入消息的長度,而不是檢測終結符\ 0x13。當然,如果協議在你的控制之下,這適用於開始。

至於你的問題,你沒有指定你發佈的代碼是否也在客戶端。

+0

不幸的是,我無法更改協議,客戶端是用於測試協議合規性的驗證應用程序。 – Steve

+0

創建它時是否設置了任何套接字選項,如SO_SNDBUF?您可以使用像http://www.microsoft.com/downloads/details.aspx?FamilyID=983b941d-06cb-4658-b7f6-3088333d062f&displaylang=en這樣的網絡監視器來查看發送的ACK字節嗎? –

0

嘗試設置TCP_NODELAY套接字選項

0

你有沒有設置插座trueNoDelay財產?當設置爲false(默認值)時,數據在發送前最多緩衝200毫秒。原因是通過限制發送的數據包數量來減少網絡流量。將NoDelay設置爲true將強制數據更早發送。

相關問題