2012-04-25 41 views
0

我有一個使用WCF服務的小文件傳輸應用程序,它通過tcp套接字發送文件和文件夾。
我的問題是,當我從客戶端取消傳輸操作(backgroundworker)時,服務器仍在client.Receive上凍結,它假設給我這個例外:An existing connection was forcibly closed by the remote host,但它不是,儘管在客戶端有偵聽器.Connected成爲falsesocket.Connected成爲false
我需要得到這個異常並處理它,所以我可以關閉流和套接字,並準備接受另一項任務!Sockets.Connected始終爲真?

客戶端:

private void worker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     List<Job> Jobs = (List<Job>)e.Argument; 
     using (Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) 
     { 
      IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 0); 
      listener.Bind(endpoint); 
      listener.Listen(1); 
      client.ConnectToClient((IPEndPoint)listener.LocalEndPoint); 
      Socket socket = listener.Accept(); 
      foreach (Job job in Jobs) 
      { 
       if (job.IsFile) 
        { 
         if (job.IsSend) 
         { SendFile(socket, job, e); } //here i send a single file. 
     //   else 
     //   { ReceiveFile(socket, job, e); } 
        } 
     //  else 
     //  { 
     //   if (job.IsSend) 
     //   { SendDir(socket, job, e); } 
     //   else 
     //   { ReceiveDir(socket, job, e); } 
     //  } 
       if (worker.CancellationPending) 
       { 
        e.Cancel = true; 
        socket.Dispose(); 
        listener.Dispose(); 
        Console.WriteLine(socket.Connected + " " + listener.Connected); 
        //it prints "FALSE FALSE" 
        return; 
       } 
      } 
     } 
    } 

private void SendFile(Socket socket, Job job, DoWorkEventArgs e) 
    { 
     UpdateInfo(job.Name, job.Icon);    //update GUI with file icon and name. 
     client.ReceiveFile((_File)job.Argument, bufferSize); //tell the client to start receiving 
     SendX(socket, ((_File)job.Argument).Path, e); //start sending.. 
    } 

private void SendX(Socket socket, string filePath, DoWorkEventArgs e) 
    { 
     using (Stream stream = File.OpenRead(filePath)) 
     { 
      byte[] buffer = new byte[bufferSize]; 
      long sum = 0; 
      int count = 0; 
      while (sum < stream.Length) 
      { 
       if (worker.CancellationPending) 
       { 
        e.Cancel = true; 
        return; 
       } 
       count = stream.Read(buffer, 0, buffer.Length); 
       socket.Send(buffer, 0, count, SocketFlags.None); 
       sum += count; 
       SumAll += count; 
       worker.ReportProgress((int)((sum * 100)/stream.Length)); 
      } 
     } 
    } 

服務器端:

public void ConnectToClient(IPEndPoint endpoint) 
    { 
     if (client == null) 
     { 
      Thread th = new Thread(unused => ConnectTh(endpoint)); 
      th.Start(); 
     } 
    } 
    private void ConnectTh(IPEndPoint endpoint) 
    { 
     client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
     client.Connect(IPAddress.Parse("127.0.0.1"), endpoint.Port); 
    } 


public void ReceiveFile(_File file, int bufferSize) 
    { 
     System.Threading.Thread th = new System.Threading.Thread(unused => ReceiveX(client, file.Name, file.Size, bufferSize)); 
     th.Start(); 
    } 

private void ReceiveX(Socket client, string destPath, long size, int bufferSize) 
    { 
     try 
     { 
      using (Stream stream = File.Create(destPath)) 
      { 
       byte[] buffer = new byte[bufferSize]; 
       long sum = 0; 
       int count = 0; 
       while (sum < size) 
       { 
        int bytesToReceive = (int)Math.Min(buffer.Length, size - sum); 
        count = client.Receive(buffer, 0, bytesToReceive, SocketFlags.None); 
        stream.Write(buffer, 0, count); 
        sum += count; 
       } 
      } 
     } 
     catch 
     { 
      if (File.Exists(destPath)) 
       File.Delete(destPath); 
      client.Dispose(); 
     } 
    } 

回答

0

你不應該(有)對正常計劃流程例外計數。

當客戶端關閉套接字時,服務器將收到一個0字節的數據包,並在您撥打Receive時繼續收到該數據包。這會導致你的while循環永遠持續下去。您應該處理count爲0的情況,並將其視爲定期「客戶關閉的連接」。 您提到的異常只發生在客戶端無法正常關閉的情況下。