/// <summary> /// 开始接收文件。返回一个 TaskCompletionStatus 值,指示是文件传输结果。 /// </summary> /// <param name="percentage">将文件传输任务进度以 0-100 的数字传递出来到这个数。</param> /// <returns>返回一个值,指示完成文件传输的结果。</returns> public TaskCompletionStatus Start(ref int percentage) { if (isAlreadyStart == false) { isAlreadyStart = true; TCP tCP = new TCP(); //建立中断信号监听 TcpListener cancelSignalListener = new TcpListener(IPAddress.Any, 50020); cancelSignalListener.Start(); //异步接受连接请求 cancelSignalListener.BeginAcceptTcpClient(new AsyncCallback(DoAcceptTcpClient), cancelSignalListener); int fragmentBufferLength = fragmentBuffer.Length; int blockBufferBufferLength = blockBuffer.Length; int blockElementsNums = 0; //指示 blockBuffer 中有多少个字节 long totalindex = FileByte / fragmentBufferLength; //文件的总片数 CommonFoundations.FileTransferTempData.TotalBlocks = totalindex; long index = 0; //接受数据片的序号 Thread.Sleep(50); //等待对面建立控制信号监听 TcpClient signalClient = new TcpClient(RemoteIP, 50023); //请求连接控制消息 signalClient.NoDelay = true; //禁用 Nagle 算法,使数据包立即发出 NetworkStream signalStream = signalClient.GetStream(); TcpListener tcpListener = new TcpListener(IPAddress.Any, 50024);//本机所有ip try { FileStream fStream = new FileStream(FilePath, FileMode.Create); tcpListener.Start(); TcpClient newClient = tcpListener.AcceptTcpClient(); NetworkStream clientStream = newClient.GetStream(); BufferedStream bufferedStream = new BufferedStream(clientStream);//建立缓冲流 using (fStream) { using (newClient) { using (clientStream) { if (clientStream.CanRead) { while (index <= totalindex) //判断传入长度(整个文件的长度等于每次传入的次数加上一开始多读取的字符串的长度) { if (index == totalindex) //最后一次循环 { int mod = (int)(FileByte % fragmentBufferLength); //最后一次传输有多少字节 if (mod == 0) //文件总字节长度是 数据片 的整数倍,即本次传输没有任何有效字节 { fragmentBufferLength = 0; //break;//放弃本次的无效数据,退出循环 } else//不是整数倍 { fragmentBufferLength = mod; } } bufferedStream.Read(fragmentBuffer, 0, fragmentBufferLength); Buffer.BlockCopy(fragmentBuffer, 0, blockBuffer, blockElementsNums, fragmentBufferLength);//把数据片中的数据追加到数据块缓存中 index++; blockElementsNums += fragmentBufferLength; Percentage = (int)(((double)index / totalindex) * 100);//计算传输百分比 percentage = Percentage; if (blockElementsNums == blockBuffer.Length)//缓存块满,需要写入到文件 { fStream.Write(blockBuffer, 0, blockBufferBufferLength); blockElementsNums = 0; } //中断传输 #region if (CommonFoundations.FileTransferTempData.CancelFTR == true) { CancelByHost = true; } //任意一方发出了取消请求 if (CancelByHost == true || CancelByOpposite == true) { if (CancelByHost == true) //自己结束的 { tCP.TCPMessageSender(RemoteIP, "CANCEL", 50020); //发送取消消息监听 BlockConfirm(ref signalStream, "OK"); //发送消息,让对面解除因为监听 Block 确认造成的阻塞 fStream.Flush(); fStream.Dispose(); fStream.Close(); File.Delete(FilePath);//删除未完成的文件 return(TaskCompletionStatus.HostCancel); } if (CancelByOpposite == true)//对面结束的,表明已经收到了 取消消息,不用再发 { fStream.Flush(); fStream.Dispose(); fStream.Close(); File.Delete(FilePath);//删除未完成的文件 return(TaskCompletionStatus.OppositeCancel); } } #endregion BlockConfirm(ref signalStream, "OK");//发送消息让对方传输下一个块 CommonFoundations.FileTransferTempData.CurrentBlocks = index; } if (blockElementsNums != 0)//缓存块里有东西,需要最后一次写入 { fStream.Write(blockBuffer, 0, blockElementsNums); } BlockConfirm(ref signalStream, "OVER");//发送消息让对方结束传输 } } } } newClient.Close(); } //catch #region catch (ArgumentNullException e) { MessageBox.Show(e.ToString()); } catch (ArgumentOutOfRangeException e) { MessageBox.Show(e.ToString()); } catch (ArgumentException e) { MessageBox.Show(e.ToString()); } catch (NotSupportedException e) { MessageBox.Show(e.ToString()); } catch (FileNotFoundException e)///File.OpenRead { MessageBox.Show(e.ToString()); } catch (IOException e) { MessageBox.Show(e.ToString()); } catch (ObjectDisposedException e) { MessageBox.Show(e.ToString()); } catch (InvalidOperationException e) { MessageBox.Show(e.ToString()); } catch (SocketException e) { MessageBox.Show(e.ToString()); } catch (Exception e) { MessageBox.Show("未知错误!\r\n" + e.ToString()); } #endregion finally //收尾工作 { cancelSignalListener.Stop(); //结束取消控制信息监听器 signalStream.Dispose(); signalClient.Close(); tcpListener.Stop();//结束监听器 } isAlreadyStart = false; return(TaskCompletionStatus.Success);//完美结束 } else { return(TaskCompletionStatus.AlreadyRun); } }
/// <summary> /// 开始发送文件。返回一个 TaskCompletionStatus 值,指示是文件传输结果。 /// </summary> /// <param name="percentage">将文件传输任务进度以 0-100 的数字传递出来到这个数。</param> /// <returns>返回一个 bool 值,指示是否完成文件传输。false 表示遭到用户中断。</returns> public TaskCompletionStatus Start(ref int percentage) { if (isAlreadyStart == false)//没有启动 { isAlreadyStart = true; TCP tCP = new TCP(); TcpListener cancelSignalListener = new TcpListener(IPAddress.Any, 50020); cancelSignalListener.Start(); //异步接受连接请求 cancelSignalListener.BeginAcceptTcpClient(new AsyncCallback(DoAcceptTcpClient), cancelSignalListener); int fragmentBufferLength = fragmentBuffer.Length; long totalindex = FileByte / fragmentBufferLength;//文件的总块数 long index = 0; //int max = 0; signalListener.Start(); //开始监听控制信息; TcpClient signalClient = signalListener.AcceptTcpClient(); //接收到控制信号连接请求,即允许建立文件传输连接 NetworkStream signalStream = signalClient.GetStream(); Thread.Sleep(50); //等待一点时间,让对面建立监听 TcpClient client = new TcpClient(RemoteIP, 50024); //初始化一个对象,并连接到目标主机(因此不需要 connect 方法) client.NoDelay = true; //禁用 Nagle 算法,使数据包立即发出 try { FileStream fStream = File.OpenRead(FilePath); //打开文件流 NetworkStream sendStream = client.GetStream(); BufferedStream bufferedStream = new BufferedStream(sendStream); //建立缓冲流 using (fStream) { using (client) { using (sendStream) { using (bufferedStream) { while ((fragmentBufferLength = fStream.Read(fragmentBuffer, 0, fragmentBufferLength)) > 0)//blockBufferLength为0时,即文件流到达结尾 { sendStream.Write(fragmentBuffer, 0, fragmentBufferLength); sendStream.Flush(); BlockServed(ref signalStream, signalClient.ReceiveBufferSize); //这是一个阻塞方法,只有收到确认后才继续传下一个数据片 index++; Percentage = (int)(((double)index / totalindex) * 100); //计算传输百分比 percentage = Percentage; if (CommonFoundations.FileTransferTempData.CancelFTR == true) { CancelByHost = true; } if (CancelByHost == true || CancelByOpposite == true) { if (CancelByHost == true) //自己结束的 { tCP.TCPMessageSender(RemoteIP, "CANCEL", 50020); //发送取消消息监听 return(TaskCompletionStatus.HostCancel); } if (CancelByOpposite == true)//对面结束的,表明已经收到了 取消消息 { return(TaskCompletionStatus.OppositeCancel); } } } } } } } } #region catch (ArgumentNullException e) { MessageBox.Show(e.ToString()); } catch (ArgumentOutOfRangeException e) { MessageBox.Show(e.ToString()); } catch (ArgumentException e) { MessageBox.Show(e.ToString()); } catch (NotSupportedException e) { MessageBox.Show(e.ToString()); } catch (FileNotFoundException e)///File.OpenRead { MessageBox.Show(e.ToString()); } catch (IOException e) { MessageBox.Show(e.ToString()); } catch (ObjectDisposedException e) { MessageBox.Show(e.ToString()); } catch (InvalidOperationException e) { MessageBox.Show(e.ToString()); } catch (SocketException e) { MessageBox.Show(e.ToString()); } catch (Exception e) { MessageBox.Show("未知错误!\r\n" + e.ToString()); } #endregion finally //收尾工作 { cancelSignalListener.Stop(); //结束取消控制信息监听器 signalStream.Dispose(); signalStream.Close(); signalClient.Close(); client.Close();//关闭客户端 signalListener.Stop(); } isAlreadyStart = false; return(TaskCompletionStatus.Success);//完美结束 } else { return(TaskCompletionStatus.AlreadyRun); } }