2009-01-12 95 views
2

我正在構建一個客戶端/服務器應用程序來定期備份某些文件。基本上,客戶端將監視某些文件的更改,並將其上傳到服務器。然後服務器將接收它們並將用遞增後綴保存它們(即「filename_v1」,「filename_v2」等)。現在,我設法完成了大部分工作,但出現了一些問題,我找不到與之相關的任何內容。用C編寫Socket編程#

在我開始之前,請注意:

  • 我盡我所能去尋找我自己的解決方案。
  • 我遵循(並完成)了幾個套接字編程教程。
  • 我不知道任何有C#和/或套接字編程經驗的人。

這裏的邏輯:

  1. 服務器啓動時,就開始聽。 (BeginAccept)
  2. 當客戶端連接時,會創建一個「worker」套接字。
  3. 工人套接字開始接收。 (BeginReceive)/客戶端發送文件(SendFile)
  4. 當收到數據時,文件被保存。 (也檢查爲早期版本,但它是這裏無關緊要。)
  5. 轉到3.(我們需要從同一個客戶端獲得更多的文件。)

1-4步的工作就好了。

下面是問題:在第5步中,即使服務器沒有收到任何消息,onDataReceive(回調方法)被調用,服務器發現自己處於無限循環狀態。我試圖關閉(或斷開)工人插座,但沒有機會在那裏。我開始懷疑,也許我的算法有點草率。

無論如何,任何意見,建議或幫助,高度讚賞。

+0

你能在這裏發佈一些代碼,所以我們可以看到可能發生什麼? – GEOCHET 2009-01-12 17:29:26

回答

1

我已經在一個套接字庫上做了一些工作,它在過去的一年中用於在.NET中傳輸醫學圖像。早期,我們很難檢測套接字何時關閉,但最終達到穩定的解決方案。

我們的應用程序使用NetworkStream來讀取/寫入套接字。我們有一個類似於您的線程,它是在新連接到達時創建的,用於讀取和寫入網絡數據。我們調用下面的方法來輪詢數據何時到達或連接何時關閉。如果您不想輪詢,可以調整該方法以使用更長的超時時間。當我們知道數據可用時,我們從NetworkStream對象讀取數據。

下面的關鍵點是零字節在套接字上發送,這似乎在套接字關閉時檢測到,如註釋中所述。 OnNetworkError方法僅用於啓動正在關閉的線程。

史蒂夫

 

protected override bool NetworkHasData() 
{ 
    if (_socket == null) 
     return false; 

    // Tells the state of the connection as of the last activity on the socket 
    if (!_socket.Connected) 
    { 
     OnNetworkError(null, true); 
     return false; 
    } 

    // This is the recommended way to determine if a socket is still active, make a 
    // zero byte send call, and see if an exception is thrown. See the Socket.Connected 
    // MSDN documentation. Only do the check when we know there's no data available 
    try 
    { 
     List readSockets = new List(); 
     readSockets.Add(_socket); 
     Socket.Select(readSockets, null, null, 100000); 
     if (readSockets.Count == 1) 
     { 
      if (_socket.Available > 0) 
       return true; 
      OnNetworkError(null, true); 
      return false; 
     } 

     _socket.Send(new byte[1], 0, 0); 
    } 
    catch (SocketException e) 
    { 
     // 10035 == WSAEWOULDBLOCK 
     if (!e.NativeErrorCode.Equals(10035)) 
      OnNetworkError(e, true); 
    } 

    return false; 
} 
 
1

我想你應該看一看WCF。爲什麼重新發明套接字編程,當你可以使用一個消息傳遞應用程序,可以很容易地通過電線傳輸字節數組?

WCF將處理您當前正在嘗試執行的安全性,數據傳輸和所有管道工作。當然,要傳輸文件,您將被迫將消息大小設置爲高於默認值......但我會認真考慮在重新編碼輪子之前使用WCF製作原型。

我建議以下資源:

2

請問你的回調實現EndReceive?

你是否傳遞一個狀態對象?如果是這樣,請將其中一個屬性作爲傳遞給BeginReceive的緩衝區,然後在回調中檢查狀態緩衝區以查看是否收到任何數據。如果沒有,請不要繼續循環。

struct SocketStateObject 
{ 
    public byte[] Buffer; 
    public Socket Socket; 
} 



Socket mySocket = new Socket(...); 
SocketStateObject state; 
state.Buffer = new byte[1024]; 
state.Socket = mySocket; 

socket.BeginReceive(state.Buffer, 0, state.Buffer.Length, 0, callback, state); 

//don't remember the signature 
public void callback(IAsyncResult a) 
{ 
    if (((SocketStateObject)a.State).Buffer.Length = 0) 
    //don't call socket.beginreceive again. 
}