2011-04-19 39 views
4

我有一個接收器和發件人客戶端,幾乎傳輸文件。這是我迄今在接收器上的東西:如何取消TCP文件傳輸c#

Thread t1; 
    int flag = 0; 
    string receivedPath; 
    public delegate void MyDelegate(string s); 
    int bytesRead = 0; 
    bool endReceive = false; 
     public Form1() 
     { 
      t1 = new Thread(new ThreadStart(StartListening)); 
      t1.Start(); 
      InitializeComponent(); 
     } 

     public class StateObject 
     { 
      // Client socket. 
      public Socket workSocket = null; 

      public const int BufferSize = 1024*100; 

      // Receive buffer. 
      public byte[] buffer = new byte[BufferSize]; 
     } 

    public static ManualResetEvent allDone = new ManualResetEvent(false); 

    public void StartListening() 
    { 
     byte[] bytes = new Byte[1024*1000]; 
     IPEndPoint ipEnd = new IPEndPoint(IPAddress.Any, 9050); 
     Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
     try 
     { 
      listener.Bind(ipEnd); 
      listener.Listen(100); 
      while (true) 
      { 
       allDone.Reset(); 
       listener.BeginAccept(new AsyncCallback(AcceptCallback), listener); 
       allDone.WaitOne(); 

       if (endReceive) 
       { 
        listener.Disconnect(true); 
       } 
      } 
     }   
     catch (Exception ex) 
     { 

     } 

    } 
    public void AcceptCallback(IAsyncResult ar) 
    { 

     allDone.Set(); 
     Socket listener = (Socket)ar.AsyncState; 
     Socket handler = listener.EndAccept(ar); 
     StateObject state = new StateObject(); 
     state.workSocket = handler; 
     handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, 
     new AsyncCallback(ReadCallback), state);    
     flag = 0; 
    } 

    public void ReadCallback(IAsyncResult ar) 
    { 
     int fileNameLen = 1; 
     String content = String.Empty; 
     StateObject state = (StateObject)ar.AsyncState; 
     Socket handler = state.workSocket; 

     try 
     { 
      bytesRead= handler.EndReceive(ar); 

     } 
     catch (SocketException x) 
     { 
      MessageBox.Show("File Transfer was cancelled"); 
      Invoke(new MyDelegate(LabelWriter), new object[] { "Waiting for connections" }); 
      if (File.Exists(receivedPath)) 
      {      
       File.Delete(receivedPath); 
       return; 
      } 
     } 
     if (endReceive) 
     { 
      handler.Disconnect(true); 
      if (File.Exists(receivedPath)) 
      { 
       File.Delete(receivedPath); 
      } 
      return; 
     } 

     if (bytesRead > 0) 
     { 
      if (flag == 0) 
      {      
       fileNameLen = BitConverter.ToInt32(state.buffer, 0); 
       string fileName = Encoding.UTF8.GetString(state.buffer, 4, fileNameLen);      
       receivedPath = fileName;      
       Invoke(new MyDelegate(LabelWriter), new object[] { "Receiving File: " + fileName }); 
       flag++; 
      } 
       if (flag >= 1) 
       { 

        BinaryWriter writer = new BinaryWriter(File.Open(receivedPath, FileMode.Append)); 
        if (flag == 1) 
        { 
         writer.Write(state.buffer, 4 + fileNameLen, bytesRead - (4 + fileNameLen)); 
         flag++; 
         ReleaseMemory(); 
        } 
        else 
         writer.Write(state.buffer, 0, bytesRead); 
         writer.Close(); 
         try 
         { 
          handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, 
               new AsyncCallback(ReadCallback), state); 
         } 
         catch (SocketException exc) 
         { 
          MessageBox.Show("File Transfer was cancelled"); 
          Invoke(new MyDelegate(LabelWriter), new object[] { "Waiting for connections" }); 
          if (File.Exists(receivedPath)) 
          {          
           File.Delete(receivedPath); 
           return; 
          } 
         }             
       } 
     } 
     else    
      Invoke(new MyDelegate(LabelWriter), new object[] {"Data Received"});   
    } 

我想達到的是取消轉移發生的能力。我想到的是將布爾值「EndReceive」設置爲false,並且每次調用ReadCallBack方法時都檢查EndReceive。如果它是假的,我斷開插座。它在停止接收文件時起作用,然而,發件人應用程序只是凍結。這基本上是我發送的:

while (true) 
     { 
      int index = 0; 
      while (index < fs.Length) 
      { 
       int bytesRead = fs.Read(fileData, index, fileData.Length - index); 
       if (bytesRead == 0) 
       { 
        break; 
       } 

       index += bytesRead; 
      } 
      if (index != 0) 
      { 
       try 
       { 
        clientSock.Send(fileData, index, SocketFlags.None); 
       } 
       catch (Exception sexc) 
       { 
        MessageBox.Show("Transfer Cancelled"); 
        return; 
       } 
       ReleaseMemory(); 
       if ((progressBar1.Value + (1024 * 1000)) > fs.Length) 
       { 
        progressBar1.Value += ((int)fs.Length - progressBar1.Value); 
       } 
       else 
        progressBar1.Value += (1024 * 1000); 

       lblSent.Text = index.ToString(); 
      } 

      if (index != fileData.Length) 
      { 
       ReleaseMemory(); 
       progressBar1.Value = 0; 
       clientSock.Close(); 
       fs.Close();     
       break; 


      } 
     } 

有什麼想法?

+1

如果我沒有錯,如果你沒有做適當的連接關係,你會看到你繼續接收,但所有0字節。我做了一個應用程序之前,客戶端將自動重新連接,如果連接丟失。所以當連接丟失時,我將接收到0字節,所以在那一刻,我只關閉客戶端,並重新建立連接。 – 2011-04-19 01:51:22

回答

2

我認爲很難強制執行中斷來處理您正在進行的批量傳輸,並使用TCP完全關閉中斷。如果你的塊大小爲1024,並且在每次傳輸完數據後,發送一個快速的ACK或者NACK字節到接收方?表示轉移的Nack將被中斷,確認表示繼續。

不幸的是,這需要接收器/發送器完全雙工,並且要小心!即使它是異步IO,如果您計劃並從同一個套接字讀寫,您也需要在單獨的線程上調用BeginReceive和BeginSend。