相信在使用0.1版的时候没开启监听就直接传送文件必将导致异常,而且传输过程中的信息是看不到的。这一篇是对上一篇进行了一些改进,并且可以了解传输的信息(加入了Log),还加入了接收或者拒绝接收文件功能。并还将代码中的类进一步优化,该封装到一起的都封装到一起实现功能的模块化。
在上一篇中,文件发送类(UdpSendFile)和文件接收类(UdpRecieveFile)是直接用UdpClient来进行发送和接收的,现在,我添加了一个新的类(UdpPeer),实现了基本的异步传输和接收数据的方法,定义了一个接口(IDataCell)作为一个数据发送单元,它包含两个方法:ToBuffer和FromBuffer,所有的发送数据(SendCell)都继承它来实现。文件发送类(UdpSendFile)和文件接收类(UdpRecieveFile)中的(UdpClient)用(UdpPeer)代替了。
在文件发送类(UdpSendFile)和文件接收类(UdpRecieveFile)中加入了Log事件,以便于我们了解文件的传输过程,在文件接收类(UdpRecieveFile)中还加入了RequestSendFile事件,当接收到一个发送文件请求时可以同意或者拒绝接收文件。下面来看看新的程序的截图。
接收端
发送端
代码展示(与上一版不同以及新增加的地方):
UdpPeer.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
namespace CSharpWin
{
/* 类UdpPeer实现了基本的异步传输和接收数据的方法
* 本类即UdpClient的封装类
*/
//定义一种释放分配资源的方法
public class UdpPeer : IDisposable
{
private UdpClient _udpClient;
private int _port = 8899; //本机端口号
private bool _started; //是否启动监听标志
//构造函数
public UdpPeer(int port)
{
_port = port;
}
//接收数据处理事件声明
public event ReceiveDataEventHandler ReceiveData;
public int Port
{
get { return _port; }
}
//设置只读属性
internal UdpClient UdpClient
{
get
{
if (_udpClient == null)
{
//可能出现设置的本地端口号被占用的情况,嵌入异常处理
bool success = false;
while (!success)
{
try
{
//实用本地端口号建立UdpClient
_udpClient = new UdpClient(_port);
success = true;
}
catch(SocketException ex)
{
_port++; //端口号自增
if (_port > 65535)
{
success = true;
throw ex;
}
}
}
//用于正常关闭UDP连接,防止异常终止
//Convert.ToByte(false),null字段为固定值
uint IOC_IN = 0x80000000;
uint IOC_VENDOR = 0x18000000;
uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
_udpClient.Client.IOControl(
(int)SIO_UDP_CONNRESET,
new byte[] { Convert.ToByte(false) },
null);
}
return _udpClient;
}
}
//启动监听
public void Start()
{
if (!_started)
{
_started = true;
//创建异步监听,从远程主机异步接收数据
ReceiveInternal();
}
}
//调用下方的数据发送函数
public void Send(IDataCell cell, IPEndPoint remoteIP)
{
//打包要发送的数据到buffer
byte[] buffer = cell.ToBuffer();
//将数据异步发送
SendInternal(buffer, remoteIP);
}
//数据发送函数
protected void SendInternal(byte[] buffer,IPEndPoint remoteIP)
{
if (!_started)
{
throw new ApplicationException("UDP Closed.");
}
//嵌入异常处理
try
{
//将数据异步发送
UdpClient.BeginSend(
buffer,
buffer.Length,
remoteIP,
new AsyncCallback(SendCallback),
null);
}
catch (SocketException ex)
{
throw ex;
}
}
//创建异步监听,从远程主机异步接收数据
protected void ReceiveInternal()
{
if (!_started)
{
return;
}
//嵌入异常处理
try
{
UdpClient.BeginReceive(
new AsyncCallback(ReceiveCallback),
null);
}
catch (SocketException ex)
{
throw ex;
}
}
//结束挂起的异步发送
private void SendCallback(IAsyncResult result)
{
//嵌入异常处理
try
{
UdpClient.EndSend(result);
}
catch (SocketException ex)
{
throw ex;
}
}
//异步监听委托对象,接收到消息后处理方法
private void ReceiveCallback(IAsyncResult result)
{
if (!_started)
{
return;
}
//设置远程主机连接,接收来自任意主机端口号的数据
IPEndPoint remoteIP = new IPEndPoint(IPAddress.Any, 0);
byte[] buffer = null;
//嵌入异常处理
try
{
//结束挂起的异步接收线程,引用的remoteEP包含发送方IP,Port
buffer = UdpClient.EndReceive(result, ref remoteIP);
}
catch (SocketException ex)
{
throw ex;
}
finally
{
//启动新的异步接收,循环往复
ReceiveInternal();
}
//调用下面的触发事件方法
OnReceiveData(new ReceiveDataEventArgs(buffer, remoteIP));
}
//接收到数据后触发数据处理事件
protected virtual void OnReceiveData(ReceiveDataEventArgs e)
{
if(ReceiveData != null)
{
//触发事件
ReceiveData(this, e);
}
}
//释放分配的资源
#region IDisposable 成员
public void Dispose()
{
_started = false;
if (_udpClient != null)
{
_udpClient.Close();
_udpClient = null;
}
}
#endregion
}
}
UdpSendFile.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.IO;
namespace CSharpWin
{
/*文件发送类
* 具体实现数据发送与接收的时序处理
*/
//定义一种释放分配资源的方法
public class UdpSendFile : IDisposable
{
private UdpPeer _udpPeer;
private string _remoteIP = "127.0.0.1";
private int _remotePort = 8900;
private int _port = 8899; //本机端口号
private string _fileName; //要发送的文件名
private SendFileManager _sendFileManage; //声明文件发送管理类
//构造函数
public UdpSendFile(
string remoteIP,
int remotePort,
int port)
{
_remoteIP = remoteIP;
_remotePort = remotePort;
_port = port;
}
//显示发送文件日志事件声明
public event TraFransfersFileLogEventHandler Log;
//传入要发送的文件名,启动文件发送方法
public string FileName
{
get { return _fileName; }
set
{
_fileName = value;
//释放先前实例化对象
if (_sendFileManage != null)
{
_sendFileManage.Dispose();
}
_sendFileManage = new SendFileManager(_fileName);
//订阅事件,将委托添加到源对象的事件中
//委托目标即事件处理函数为SendFileManageReadFileBuffer
_sendFileManage.ReadFileBuffer += new ReadFileBufferEventHandler(
SendFileManageReadFileBuffer);
//初始化文件头
TraFransfersFileStart ts = new TraFransfersFileStart(
new FileInfo(_fileName).Name,
_sendFileManage.Length,
_sendFileManage.PartCount,
_sendFileManage.PartSize);
//发送第一包数据,即文件的信息数据
Send((int)Command.RequestSendFile, ts);
}
}
//设置只读属性
public UdpPeer UdpPeer
{
get
{
if (_udpPeer == null)
{
_udpPeer = new UdpPeer(_port);
//订阅事件,将委托添加到源对象的事件中
//委托目标即事件处理函数为UdpPeerReceiveData
_udpPeer.ReceiveData += new ReceiveDataEventHandler(UdpPeerReceiveData);
}
return _udpPeer;
}
}
//设置远程主机
public IPEndPoint RemoteEP
{
get { return new IPEndPoint(IPAddress.Parse(_remoteIP), _remotePort); }
}
//启动监听
public void Start()
{
UdpPeer.Start();
//打印日志
OnLog("开始侦听。");
}
/*Log触发事件,打印日志信息
virtual是告诉其它想继承于他的类 ,可以重写我的这个方法或属性*/
protected virtual void OnLog(TraFransfersFileLogEventArgs e)
{
if (Log != null)
{
Log(this, e);
}
}
//调用上面的虚函数
private void OnLog(string message)
{
OnLog(new TraFransfersFileLogEventArgs(message));
}
//读取文件缓冲事件处理函数
private void SendFileManageReadFileBuffer(
object sender, ReadFileBufferEventArgs e)
{
TraFransfersFile ts = new TraFransfersFile(
e.Index, e.Buffer);
//发送文件数据块
Send((int)Command.RequestSendFilePack, ts);
//打印日志
OnLog(string.Format(
"发送第 {0} 部分,大小为 {1} byte",
e.Index.ToString(),
e.Buffer.Length.ToString()));
}
//数据发送函数
private void Send(int messageID, object data, IPEndPoint remoteIP)
{
//打包要发送的数据到buffer
SendCell cell = new SendCell(messageID, data);
byte[] buffer = cell.ToBuffer();
//将数据异步发送
UdpPeer.Send(cell, remoteIP);
}
//调用上面的发送函数
private void Send(int messageID, object data)
{
Send(messageID, data, RemoteEP);
}
//UdpPeer接收数据后触发的数据处理方法
private void UdpPeerReceiveData(object sender, ReceiveDataEventArgs e)
{
//解析收到的数据
SendCell cell = new SendCell();
cell.FromBuffer(e.Buffer);
switch (cell.MessageID)
{
//根据消息标识符MessageID,确定处理逻辑
case (int)Command.ResponeSendFile:
OnResponeSendFile(cell);
break;
case (int)Command.ResponeSendFilePack:
ResponeSendFilePack(cell);
break;
}
}
//接收方响应文件发送处理方法
private void OnResponeSendFile(SendCell cell)
{
//若收到数据内容为"OK"则开始发送数据
if (cell.Data.ToString() == "OK")
{
//启动文件发送管理类的读文件流方法
_sendFileManage.Read();
//打印日志
OnLog("对方同意接收文件。");
}
else
{
//打印日志
OnLog("对方拒绝接收文件。");
}
}
//接收方响应文件发送数据块处理方法
private void ResponeSendFilePack(SendCell cell)
{
//若收到数据内容为"END"则停止发送数据
if (cell.Data.ToString() == "END")
{
//释放文件发送管理类
_sendFileManage.Dispose();
_sendFileManage = null;
//打印日志
OnLog("文件发送完成。");
}
//否则继续发送数据
else
{
_sendFileManage.Read();
}
}
//释放分配的资源
#region IDisposable 成员
public void Dispose()
{
if (_udpPeer != null)
{
_udpPeer.Dispose();
_udpPeer = null;
}
if (_sendFileManage != null)
{
_sendFileManage.Dispose();
_sendFileManage = null;
}
}
#endregion
}
}
UdpReceiveFile.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
namespace CSharpWin
{
/* 文件接收类
* 具体实现数据的发送与接收的时序处理
*/
//定义一种释放分配资源的方法
public class UdpReceiveFile : IDisposable
{
private UdpPeer _udpPeer;
private int _port = 8900;
private string _path; //文件存储位置
private ReceiveFileManager _receiveFileManager;
//构造函数
public UdpReceiveFile(string path, int port)
{
_path = path;
_port = port;
}
//显示发送文件日志事件声明
public event TraFransfersFileLogEventHandler Log;
//要求发送文件事件声明
public event RequestSendFileEventHandler RequestSendFile;
//设置只读属性
public UdpPeer UdpPeer
{
get
{
if (_udpPeer == null)
{
_udpPeer = new UdpPeer(_port);
//订阅事件,将委托添加到源对象的事件中
//委托目标即事件处理函数为UdpPeerReceiveData
_udpPeer.ReceiveData += new ReceiveDataEventHandler(UdpPeerReceiveData);
}
return _udpPeer;
}
}
//启动监听
public void Start()
{
UdpPeer.Start();
OnLog("开始侦听。");
}
//由receiveFile_RequestSendFile事件处理方法调用
public void AcceptReceive(RequestSendFileEventArgs e)
{
TraFransfersFileStart traFransfersFileStart = e.TraFransfersFileStart;
IPEndPoint remoteIP = e.RemoteIP;
//拒绝接收
if (e.Cancel)
{
Send((int)Command.ResponeSendFile, "NO", remoteIP);
OnLog(string.Format(
"拒绝接收文件 {0},来自 {1}。",
_receiveFileManager.FileName,
remoteIP.ToString()));
}
//同意接收
else
{
_receiveFileManager = new ReceiveFileManager(
_path,
traFransfersFileStart.FileName,
traFransfersFileStart.PartCount,
traFransfersFileStart.PartSize,
traFransfersFileStart.Length);
Send((int)Command.ResponeSendFile, "OK", remoteIP);
OnLog(string.Format(
"同意接收文件 {0},来自 {1}。",
_receiveFileManager.FileName,
remoteIP.ToString()));
}
}
/*Log触发事件,打印日志信息
virtual是告诉其它想继承于他的类 ,可以重写我的这个方法或属性*/
protected virtual void OnLog(TraFransfersFileLogEventArgs e)
{
if(Log != null)
{
Log(this,e);
}
}
//调用上面的虚函数
private void OnLog(string message)
{
OnLog(new TraFransfersFileLogEventArgs(message));
}
//触发RequestSendFile事件
protected virtual void OnRequestSendFile(RequestSendFileEventArgs e)
{
if (RequestSendFile != null)
{
RequestSendFile(this, e);
}
}
//数据发送函数
private void Send(int messageID, object data, IPEndPoint remoteIP)
{
SendCell cell = new SendCell(messageID, data);
UdpPeer.Send(cell, remoteIP);
}
//UdpPeer接收数据后触发的数据处理方法
private void UdpPeerReceiveData(object sender, ReceiveDataEventArgs e)
{
//解析收到的数据
SendCell cell = new SendCell();
cell.FromBuffer(e.Buffer);
//根据消息标识符MessageID,确定处理逻辑
switch (cell.MessageID)
{
case (int)Command.RequestSendFile:
OnStartRecieve((TraFransfersFileStart)cell.Data, e.RemoteIP);
break;
case (int)Command.RequestSendFilePack:
OnRecieveBuffer((TraFransfersFile)cell.Data, e.RemoteIP);
break;
}
}
//当接收到的是文件数据块时的处理方法
private void OnRecieveBuffer(
TraFransfersFile traFransfersFile,
IPEndPoint remoteEP)
{
_receiveFileManager.ReceiveBuffer(
traFransfersFile.Index,
traFransfersFile.Buffer);
//判断是否为最后一包
if (_receiveFileManager.PartCount == traFransfersFile.Index + 1)
{
Send((int)Command.ResponeSendFilePack, "END", remoteEP);
OnLog(string.Format(
"{0} 接收第 {1} 部分,{2}byte。",
_receiveFileManager.FileName,
traFransfersFile.Index,
traFransfersFile.Buffer.Length));
OnLog(_receiveFileManager.FileName + " 接收完成。");
}
else
{
Send((int)Command.ResponeSendFilePack, "OK", remoteEP);
OnLog(string.Format(
"{0} 接收第 {1} 部分,{2}byte。",
_receiveFileManager.FileName,
traFransfersFile.Index,
traFransfersFile.Buffer.Length));
}
}
//当接收到的是文件头信息时的处理方法
private void OnStartRecieve(
TraFransfersFileStart traFransfersFileStart,
IPEndPoint remoteEP)
{
//调用OnRequestSendFile去触发事件
OnRequestSendFile(
new RequestSendFileEventArgs(
traFransfersFileStart,
remoteEP));
}
#region IDisposable 成员
public void Dispose()
{
if(_udpPeer != null)
{
_udpPeer.Dispose();
_udpPeer = null;
}
if (_receiveFileManager != null)
{
_receiveFileManager.Dispose();
_receiveFileManager = null;
}
}
#endregion
}
}
TraFransfersFileLogEventHandler.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharpWin
{
/* 声明一个文件传输日志事件的委托
*/
//声明委托
public delegate void TraFransfersFileLogEventHandler(
object sender,
TraFransfersFileLogEventArgs e);
//定义委托事件的参数类型,继承自system.EventArgs
public class TraFransfersFileLogEventArgs : EventArgs
{
private string _messgae;
//构造函数
public TraFransfersFileLogEventArgs(string message)
: base()
{
_messgae = message;
}
public string Message
{
get { return _messgae; }
}
}
}
RequestSendFileEventHandler.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Net;
namespace CSharpWin
{
/* 声明一个请求文件传输事件的委托
*/
//声明委托
public delegate void RequestSendFileEventHandler(
object sender,
RequestSendFileEventArgs e);
//定义委托事件的参数类型,继承自system.CancelEventArgs,一个可以取消的事件
public class RequestSendFileEventArgs : CancelEventArgs
{
private TraFransfersFileStart _traFransfersFileStart;
private IPEndPoint _remoteIP;
//该构造函数将调用CancelEventArgs.CancelEventArgs()
public RequestSendFileEventArgs()
: base()
{
}
//构造函数
public RequestSendFileEventArgs(
TraFransfersFileStart traFransfersFileStart,
IPEndPoint remoteIP)
: base()
{
_traFransfersFileStart = traFransfersFileStart;
_remoteIP = remoteIP;
}
//可取消事件的构造函数
public RequestSendFileEventArgs(
TraFransfersFileStart traFransfersFileStart,
IPEndPoint remoteIP,
bool cancel)
: base(cancel)
{
_traFransfersFileStart = traFransfersFileStart;
_remoteIP = remoteIP;
}
public IPEndPoint RemoteIP
{
get { return _remoteIP; }
set { _remoteIP = value; }
}
public TraFransfersFileStart TraFransfersFileStart
{
get { return _traFransfersFileStart; }
set { _traFransfersFileStart = value; }
}
}
}
ReadFileObject.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharpWin
{
/*
自定义的一个与TraFransfersFile类相对应的类
*/
internal class ReadFileObject
{
private int _index;
private byte[] _buffer;
public ReadFileObject(int index, byte[] buffer)
{
_index = index;
_buffer = buffer;
}
public int Index
{
get { return _index; }
set { _index = value; }
}
public byte[] Buffer
{
get { return _buffer; }
set { _buffer = value; }
}
}
}
ReceiveDataEventHandler.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
namespace CSharpWin
{
/* 声明一个接收数据处理事件的委托
*/
//声明委托
public delegate void ReceiveDataEventHandler(
object sender,
ReceiveDataEventArgs e);
//定义委托事件的参数类型,继承自system.EventArgs
public class ReceiveDataEventArgs : EventArgs
{
private byte[] _buffer;
private IPEndPoint _remoteIP;
public ReceiveDataEventArgs() { }
//构造函数
public ReceiveDataEventArgs(byte[] buffer, IPEndPoint remoteIP)
: base()
{
_buffer = buffer;
_remoteIP = remoteIP;
}
public byte[] Buffer
{
get { return _buffer; }
set { _buffer = value; }
}
public IPEndPoint RemoteIP
{
get { return _remoteIP; }
set { _remoteIP = value; }
}
}
}
Command.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharpWin
{
/* 定义MessageID
* 即传输协议控制字段的一个枚举类型
*/
public enum Command
{
RequestSendFile = 0x000001,
ResponeSendFile = 0x100001,
RequestSendFilePack = 0x000002,
ResponeSendFilePack = 0x100002,
}
}
RequestSendFileEventHandler.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Net;
namespace CSharpWin
{
/* 声明一个请求文件传输事件的委托
*/
//声明委托
public delegate void RequestSendFileEventHandler(
object sender,
RequestSendFileEventArgs e);
//定义委托事件的参数类型,继承自system.CancelEventArgs,一个可以取消的事件
public class RequestSendFileEventArgs : CancelEventArgs
{
private TraFransfersFileStart _traFransfersFileStart;
private IPEndPoint _remoteIP;
//该构造函数将调用CancelEventArgs.CancelEventArgs()
public RequestSendFileEventArgs()
: base()
{
}
//构造函数
public RequestSendFileEventArgs(
TraFransfersFileStart traFransfersFileStart,
IPEndPoint remoteIP)
: base()
{
_traFransfersFileStart = traFransfersFileStart;
_remoteIP = remoteIP;
}
//可取消事件的构造函数
public RequestSendFileEventArgs(
TraFransfersFileStart traFransfersFileStart,
IPEndPoint remoteIP,
bool cancel)
: base(cancel)
{
_traFransfersFileStart = traFransfersFileStart;
_remoteIP = remoteIP;
}
public IPEndPoint RemoteIP
{
get { return _remoteIP; }
set { _remoteIP = value; }
}
public TraFransfersFileStart TraFransfersFileStart
{
get { return _traFransfersFileStart; }
set { _traFransfersFileStart = value; }
}
}
}
TraFransfersFileLogEventHandler.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharpWin
{
/* 声明一个文件传输日志事件的委托
*/
//声明委托
public delegate void TraFransfersFileLogEventHandler(
object sender,
TraFransfersFileLogEventArgs e);
//定义委托事件的参数类型,继承自system.EventArgs
public class TraFransfersFileLogEventArgs : EventArgs
{
private string _messgae;
//构造函数
public TraFransfersFileLogEventArgs(string message)
: base()
{
_messgae = message;
}
public string Message
{
get { return _messgae; }
}
}
}
UdpSendFileDemo.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using CSharpWin;
using System.IO;
namespace UdpSendFileDemo
{
public partial class Form1 : Form
{
private UdpSendFile sendFile;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == DialogResult.OK)
{
//获取文件路径名
sendFile.FileName = ofd.FileName; //发送数据
}
}
private void button2_Click(object sender, EventArgs e)
{
sendFile = new UdpSendFile( //实例化UdpSendFile
tbRemoteIP.Text,
int.Parse(tbRemotePort.Text),
int.Parse(tbLocalPort.Text));
//订阅事件,将委托添加到源对象的事件中
//委托目标即事件处理函数为sendFile_Log
sendFile.Log += new TraFransfersFileLogEventHandler(sendFile_Log);
sendFile.Start(); //启动监听
}
//在ListBox1中显示传输日志信息
void sendFile_Log(object sender, TraFransfersFileLogEventArgs e)
{
/*MethodInvoker 提供一个简单委托,该委托用于调用含 void 参数列表的方法。
在对控件的 Invoke 方法进行调用时或需要一个简单委托又不想自己定义时可以使用该委托*/
//Invoke:在拥有此控件的基础窗口句柄的线程上执行委
Invoke(new MethodInvoker(delegate()
{
int index = listBox1.Items.Add(e.Message);
//让ListBox1保持显示最新日志信息
listBox1.SelectedIndex = index;
}));
}
//引发 Closed 事件,让一个窗体关闭了,整个程序都关闭
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
if (sendFile != null)
{
sendFile.Dispose();
}
}
}
}
ReceiveFileDemo.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using CSharpWin;
namespace ReceiveFileDemo
{
public partial class Form1 : Form
{
private UdpReceiveFile receiveFile;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
receiveFile = new UdpReceiveFile(
Application.StartupPath, //文件存储位置为当前目录
int.Parse(tbLocalPort.Text));
//订阅事件,将委托添加到源对象的事件中
//委托目标即事件处理函数为recieveFile_Log
receiveFile.Log += new TraFransfersFileLogEventHandler(recieveFile_Log);
//委托目标即事件处理函数为receiveFile_RequestSendFile
receiveFile.RequestSendFile +=
new RequestSendFileEventHandler(receiveFile_RequestSendFile);
receiveFile.Start(); //启动监听
}
//RequestSendFile所触发的事件委托目标
void receiveFile_RequestSendFile(object sender, RequestSendFileEventArgs e)
{
if (MessageBox.Show(string.Format(
"是否接收文件 {0},来自 {1}。",
e.TraFransfersFileStart.FileName,
e.RemoteIP.ToString()),
"接收文件",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question) == DialogResult.No)
{
//不接收文件,取消事件
e.Cancel = true;
}
//调用receiveFile的AcceptReceive方法向发送方回复是否接收文件信息
receiveFile.AcceptReceive(e);
}
//在ListBox1中显示传输日志信息
void recieveFile_Log(object sender, TraFransfersFileLogEventArgs e)
{
/*MethodInvoker 提供一个简单委托,该委托用于调用含 void 参数列表的方法。
在对控件的 Invoke 方法进行调用时或需要一个简单委托又不想自己定义时可以使用该委托*/
//Invoke:在拥有此控件的基础窗口句柄的线程上执行委
Invoke(new MethodInvoker(delegate()
{
int index = listBox1.Items.Add(e.Message);
//让ListBox1保持显示最新日志信息
listBox1.SelectedIndex = index;
}));
}
//引发 Closed 事件,让一个窗体关闭了,整个程序都关闭
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
if (receiveFile != null)
{
receiveFile.Dispose();
}
}
}
}