簡體   English   中英

通過TCP套接字發送大量數據

[英]sending a large amount of data throught TCP socket

這是我在這個論壇上發布的第一個問題,我是c#世界的初學者,所以這對我來說很有意思,但我面臨着通過套接字發送大量數據的一些問題,所以這是更多細節關於我的問題:

我正在通過TCP套接字發送5 Mo的二進制映像,在接收部分我保存結果(收到的數據)並且只獲得1.5 Mo ==>數據已丟失(我比較了原始文件和生成的文件它向我展示了錯過的部分)這是我使用的代碼:

private void senduimage_Click(object sender, EventArgs e)
{
    if (!user.clientSocket_NewSocket.Connected)
    {
        Socket clientSocket_NewSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        user.clientSocket_NewSocket = clientSocket_NewSocket;
        System.IAsyncResult _NewSocket = user.clientSocket_NewSocket.BeginConnect(ip_address, NewSocket.Transceiver_TCP_Port, null, null);
        bool successNewSocket = _NewSocket.AsyncWaitHandle.WaitOne(2000, true);
     }
     byte[] outStream = System.Text.Encoding.ASCII.GetBytes(Uimage_Data);
     user.clientSocket_NewSocket.Send(outStream);
 }

在他們說要將數據分成塊的論壇中,這是一個解決方案,如果是這樣我怎么能這樣做,我已經嘗試但它沒有用!

有很多不同的解決方案但是分塊通常是一個很好的解決方案,你可以盲目地做這個,你繼續填充你的臨時緩沖區,然后把它放到一些狀態緩沖區,直到你遇到一些任意的令牌或緩沖區沒有完全填滿,或者你可以遵守每個tcp 消息的某種合同(消息是要接收的整體數據)。

如果你要考慮做某種合同,那么做一些事情就像消息的前N個字節是描述符,你可以根據需要做大或小,但你的臨時緩沖區只能在前面讀取這個大小從溪流。

典型的標題可能是這樣的:

public struct StreamHeader // 5 bytes
{
   public byte MessageType {get;set;} // 1 byte
   public int MessageSize {get;set;}  // 4 bytes
}

所以你會讀到它,如果它足夠小,可以將完整的消息大小分配給臨時緩沖區並全部讀取,或者如果你認為它太大,將它分成幾部分並繼續讀取,直到你收到的總字節數與MessageSize相匹配標題結構的一部分。

可能你還沒有在C#中閱讀有關套接字使用的文檔。 http://msdn.microsoft.com/en-us/library/ms145160.aspx

內部緩沖區無法存儲您提供的所有數據以發送方法。 解決問題的可能方法就像您所說的將數據划分為塊。

int totalBytesToSend = outstream.length;     int bytesSend = 0;
while(bytesSend < totalBytesToSend )
    bytesSend+= user.clientSocket_NewSocket.Send(outStream, bytesSend, totalBytesToSend - bytesSend,...);

我懷疑你的一個問題是你沒有打電話給EndConnect 從MSDN文檔:

必須通過調用EndConnect方法來完成異步BeginConnect操作。

還有,等待: -

bool successNewSocket = _NewSocket.AsyncWaitHandle.WaitOne(2000,true);

可能總是假的,因為沒有任何東西將事件設置為信號狀態。 通常,您可以為BeginConnect函數指定一個回調函數,並在回調中指定您調用EndConnect並將事件的狀態設置為發信號。 請參閱此MSDN頁面上的示例代碼。

UPDATE

我想我看到了另一個問題: -

byte[] outStream = System.Text.Encoding.ASCII.GetBytes(Uimage_Data);

我不知道什么類型的Uimage_Data,但我真的不認為你想將它轉換為ASCII。 數據中的零可以表示數據字節的結尾(或者可能是26或其他ASCII碼)。 關鍵是,編碼過程可能正在改變數據。

你能提供Uimage_Data對象的類型嗎?

最有可能的問題是,在將所有數據傳輸到服務器之前,您正在關閉客戶端套接字,因此它將被丟棄。

默認情況下,關閉套接字時,將丟棄所有未傳輸的數據(位於操作系統緩沖區中)。 有幾個解決方案:

[1]設置SO_LINGER(參見http://developerweb.net/viewtopic.php?id=2982)[2 ]讓服務器向客戶端發送確認,並且在收到之前不要關閉客戶端套接字它。 [3]在關閉套接字之前等到客戶端輸出緩沖區為空(使用getsocketopt SO_SND_BUF進行測試 - 我不確定c#上的語法)。

你真的應該測試Send()的返回值。 雖然理論上它應該阻塞直到它發送所有數據,但我想要實際驗證,並且如果存在不匹配,至少會打印錯誤消息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM