2012-02-16 77 views
1

這並不總是會發生。但它比完全接收字節更經常發生。我的服務器程序收到的字節不完整。爲什麼?我正在使用C#.net套接字

這是我的客戶PROG如何發送字節到我的服務器PROG:

public void sendBytes() 
{ 
    FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 
    TcpClient cli = tcpServer; //tcpServer is a global TcpClient variable I use to connect to the server. 
    NetworkStream ns = cli.GetStream(); 

    CopyStreamToStream(fs, ns, null); 
    ns.Flush(); 
} 

public static void CopyStreamToStream(Stream source, Stream destination, Action<Stream, Stream, Exception> completed) 
{ 
    byte[] buffer = new byte[0x1000]; 
    int read; 

    while ((read = source.Read(buffer, 0, buffer.Length)) > 0) // <- client loop 
     destination.Write(buffer, 0, read); 
} 

這是如何我的服務器PROG從我的客戶PROG接收字節:

FileStream ms = new FileStream(tmpFile, FileMode.Create, FileAccess.Write); 
do 
{ 
    int szToRead = s.Available; //s is a socket 
    byte[] buffer = new byte[szToRead]; 

    int szRead = s.Receive(buffer, szToRead, SocketFlags.None); 
    if (szRead > 0) 
     ms.Write(buffer, 0, szRead);    
} 
while(s.Available != 0); //i also tried ms.length < size_of_file_to_be_received_in_bytes 

我跨進程序和看着這些值,我不知道是什麼原因導致缺少接收的字節。我不知道問題是與客戶編或服務器編。

我不知道這是否相關,但是當我嘗試進入客戶端循環(觀察fs.length的值並檢查它是否會在服務器中接收)時,所有4次嘗試發送一個文件從客戶端到服務器成功。但是當我沒有看到客戶端循環,並且只監視服務器應用程序(查看ms.length的值)時,4次嘗試向服務器發送文件的嘗試中只有1次成功。在3次失敗的嘗試中,ms.length小於源文件的字節(我在文件的屬性中檢查過它)。

This是我根據這從

附加信息:

在原代碼(從我根據我的程序的網站),環都有不同的狀態:

FileStream ms = new FileStream(tmpFile, FileMode.Create, FileAccess.Write); 
do 
{ 
    int szToRead = s.Available; //s is a socket 
    byte[] buffer = new byte[szToRead]; 

    int szRead = s.Receive(buffer, szToRead, SocketFlags.None); 
    if (szRead > 0) 
     ms.Write(buffer, 0, szRead);    
} 
while(SocketConnected(s)); // <--- i changed this in my program 

private static bool SocketConnected(Socket s) 
{ 
    return !(s.Poll(1000, SelectMode.SelectRead) && (s.Available == 0)); 
} 

我認爲SocketConnected測試如果套接字仍然連接,因爲客戶端程序的原始代碼是這樣的:

CopyStreamToStream(fs, ns, null); 
ns.Flush(); 
ns.Close(); 

我從程序中刪除了ns.Close(),因爲我想維護客戶端應用程序與服務器的連接。因此,我希望能夠檢查是否已完成讀取來自客戶端應用程序的所有字節,而無需關閉客戶端的套接字連接。

+0

你有沒有考慮使用'Stream.CopyTo()'[假設你在.NET 4.0] – yas4891 2012-02-16 19:10:17

+0

我想推薦你使用[Stream.CopyTo方法(流)](http://msdn.microsoft.com/en-us/library/dd782932.aspx)而不是'CopyStreamToStream'函數。 – 2012-02-16 19:11:50

+0

我會研究一下。感謝您的建議。 – Xel 2012-02-16 19:45:03

回答

4

如果可用爲零,這並不意味着您已完成讀取字節。這意味着目前,在這個納秒內,沒有字節排隊。服務器怎麼知道將來會有多少字節?

在近似值中,Available的每個單獨使用都是錯誤!

刪除可用的所有用法。相反,總是嘗試讀取完整的緩衝區。如果你得到0這意味着套接字已經關閉,你就完成了。

編輯:下面是一些經典的讀碼:

var buffer = new byte[8192]; 
while(true) { 
var readCount = stream.Read(buffer, 0, buffer.Length); 
if (readCount == 0) break; 
outputStream.Write(buffer, 0, readCount); 
} 
+0

是不是\ 0的終結者? – Thomas 2012-02-16 19:23:17

+0

終結者是什麼? – usr 2012-02-16 19:29:13

+0

@usr對不起。我不知道我應該如何「讀一個完整的緩衝區」。你能以某種方式提供一個關於如何做到這一點的示例代碼? – Xel 2012-02-16 19:46:19

相關問題