利用Socket进行大文件传输
时间:2010-08-29 来源:三只米
最近接触到利用socket进行大文件传输的技术,有些心得,与大家分享.首先看看这个过程是怎么进行的(如下图):
所以,我们需要三个socket在窗体加载的时候初始化:
1. 等到收货请求的socket(即等待对方向自己发出发送文件的请求:monitorSocket,端口:monitorPort)
2. 接收收货方响应的socket(即对方是否愿意接收大文件的回应:responseSocket:端口:responsePort)
3. 收货方收货的socket(即接收大文件:receiveSocket:端口:receivePort)
界面的设计如下(由于没有建立服务器,所以在通信时需要首先知道对方的IP和等待请求的端口):
具体步骤:
1. 在发送方和接收方的主窗体界面中分别将对方的IP和等待对方发送请求的端口填入;
2. Browser_Click(按钮的点击事件),主要完成以下操作:
(1)选择要发送的文件,并得到文件名fileName;
(2)将文件名(fileName),本机IP(localIP)和本机接收对方回应的端口(responsePort)发送给对方的monitorSocket端口
3. 接收方接收发送方文件传输请求.在接收方的monitorSocket中完成以下操作:
(1)解析出发送方传递的三个信息(fileName,responsePort和monitorSocket)
(2)弹出另存为窗口.定义是否接收的变量bool isReceive = false;若点击保存,则isReceive=true;
(3)将isReceive,本机IP和本机接收大文件的端口(receivePort)发送给发送方
4. 发送等待接收方的回复.主要完成以下操作:
(1)解析出接收方回复的信息,看对方是否同意接收,并且得到对方的IP和接受文件的端口
若对方同意接收:
(2)连接到对方接收文件的端口(即receviPort)
(3)创建文件流fileStream
(4)得到文件流的长度fileStream.Length(long型数据,比int类型传的数据量的上限更高),并且先将文件流的长度发送给接收方,让其准备足够的缓冲区
(5)对文件分包,每个包大小为partSize
(6)建一个缓冲区buffer大小为partSize,从fileStream向buffer中写数据,并将buffer中的数据发送,这个过程一直循环,直到所有的数据都写完(循环的次数为long partCount =fileSize/partSize,).
5. 接收方接收文件,主要完成以下操作:
(1)首先接收到文件流的长度
(2)定义一个文件流fileStream
(3)定义一个接收数据的缓冲区bufferData,长度为8096(这个数字可以调整)
(4)将接收的数据写到bufferData中,每次写入8096字节,将bufferData中的数据写到文件流fileStream中,直到所以的数据都写入
相关代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO; namespace SocketTest
{
public partial class FormChat : Form
{
public FormChat()
{
InitializeComponent();
} //声明本机ip
private IPAddress localIP = null; //接收对方信息的socket
private Socket socketReceiveMsg = null;
private int portReceiveMsg;
private Thread threadReceiveMsg = null; //是否接受文件的Socket
private Socket socketWaiting = null;
private int portWaiting;
private Thread threadWaiting = null; //等待对方响应是否接受的socket
private Socket socketResponse = null;
private int portResponse;
private Thread threadResponse = null; //接收文件的Socket
private Socket socketReceiveData;
private int portReceiveData;
private Thread threadReceiveData; private void rtbHistory_Load(object sender, EventArgs e)
{
IPHostEntry hostEntry = Dns.GetHostEntry(Dns.GetHostName());
this.localIP = hostEntry.AddressList[1];
this.txtLocalIP.Text = this.localIP.ToString(); Random random = new Random();
this.portWaiting = random.Next(20000, 30000);
this.portReceiveMsg = random.Next(10000,20000);
this.portReceiveData = random.Next(20000, 40000);
this.portResponse = random.Next(10000,30000);
this.txtLocalReceiveMsgPort.Text = this.portReceiveMsg.ToString();
this.txtLocalWaitingPort.Text = this.portWaiting.ToString(); IPEndPoint endPointReceiveMsg = new IPEndPoint(this.localIP, this.portReceiveMsg);
this.socketReceiveMsg = new Socket(endPointReceiveMsg.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
this.socketReceiveMsg.Bind(endPointReceiveMsg);
this.threadReceiveMsg = new Thread(new ThreadStart(ReceiveMsgListener));
this.threadReceiveMsg.Start(); IPEndPoint endPointWaiting = new IPEndPoint(this.localIP, this.portWaiting);
this.socketWaiting = new Socket(endPointWaiting.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
this.socketWaiting.Bind(endPointWaiting);
this.threadWaiting = new Thread(new ThreadStart(WaitingListener));
this.threadWaiting.Start(); IPEndPoint endPointResponse = new IPEndPoint(this.localIP, this.portResponse);
this.socketResponse = new Socket(endPointResponse.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
this.socketResponse.Bind(endPointResponse);
this.threadResponse = new Thread(new ThreadStart(ResponseListener));
this.threadResponse.Start(); IPEndPoint endPointReceiveData = new IPEndPoint(this.localIP, this.portReceiveData);
this.socketReceiveData = new Socket(endPointReceiveData.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
this.socketReceiveData.Bind(endPointReceiveData);
this.threadReceiveData = new Thread(new ThreadStart(ReceiveDataListener));
this.threadReceiveData.Start();
} private void ReceiveMsgListener()
{
this.socketReceiveMsg.Listen(10); while (true)
{
Socket socketTemp = this.socketReceiveMsg.Accept(); byte[] buffer = new byte[1024];
int byteCount = socketTemp.Receive(buffer); string message = Encoding.Default.GetString(buffer);
this.rtbHistory.AppendText(message);
}
} //等待对方的文件发送请求
private void WaitingListener()
{
this.socketWaiting.Listen(10); while (true)
{
Socket socketTemp = this.socketWaiting.Accept(); this.Invoke(new MyDelegete(SaveShow),socketTemp);
}
} private delegate void MyDelegete(Socket socket); private void SaveShow(Socket socketTemp)
{
byte[] buffer = new byte[1024];
int byteCount = socketTemp.Receive(buffer);
string request = Encoding.Default.GetString(buffer, 0, byteCount); string fileName = request.Substring(0, request.IndexOf("[fileName]"));
string ip = request.Substring(request.IndexOf("[fileName]") + 10, request.IndexOf("[ip]") - (request.IndexOf("[fileName]") + 10));
string port = request.Substring(request.IndexOf("[ip]") + 4, request.IndexOf("[port]") - (request.IndexOf("[ip]") + 4));
int remoteResponsePort = int.Parse(port); SaveFileDialog saveFileDlg = new SaveFileDialog(); saveFileDlg.FileName = fileName; bool isReceive = false; if (saveFileDlg.ShowDialog() == DialogResult.OK)
{
isReceive = true; this.txtSaveAs.Text = saveFileDlg.FileName;
} else
{
isReceive = false;
this.txtSaveAs.Text = "";
}
//向发送方发出回复
IPEndPoint endPointRemote = new IPEndPoint(IPAddress.Parse(this.txtRemoteIP.Text), remoteResponsePort);
Socket socektResponse = new Socket(endPointRemote.AddressFamily, SocketType.Stream, ProtocolType.Tcp); socektResponse.Connect(endPointRemote); if (socektResponse.Connected)
{
string messageResponse = string.Format("{0}[isReceive]{1}[port]",isReceive,this.portReceiveData); byte[] bufferResponse = Encoding.Default.GetBytes(messageResponse); socektResponse.Send(bufferResponse);
}
} //等到接收方的回复
private void ResponseListener()
{
this.socketResponse.Listen(10); while (true)
{
Socket socketTemp = this.socketResponse.Accept(); byte[] buffer = new byte[1024];
int byteCount = socketTemp.Receive(buffer); string messageResponse = Encoding.Default.GetString(buffer, 0, byteCount); bool isReceive = bool.Parse(messageResponse.Substring(0, messageResponse.IndexOf("[isReceive]")));
string portReceiveRemote = messageResponse.Substring(messageResponse.IndexOf("[isReceive]") + 11, messageResponse.IndexOf("[port]") - (messageResponse.IndexOf("[isReceive]") + 11)); if (isReceive)
{
//对方愿意接收文件,准备发送
IPEndPoint endPointRemote = new IPEndPoint(IPAddress.Parse(this.txtRemoteIP.Text), int.Parse(portReceiveRemote));
Socket socketTransmint = new Socket(endPointRemote.AddressFamily, SocketType.Stream, ProtocolType.Tcp); socketTransmint.Connect(endPointRemote); if (socketTransmint.Connected)
{
string filePath = this.txtFilePath.Text; //创建文件流
FileStream fileStream = new FileStream(filePath, FileMode.Open);
//得到文件流的长度
//int fileSize = (int)fileStream.Length;
long fileSize = fileStream.Length;
//先将要发送的文件长度发送给接收方,让对方准备缓冲区
socketTransmint.Send(BitConverter.GetBytes(fileSize));
//定义一个每次要发送的文件的大小(10M)
//int partSize = 10 * 1024 * 1024;
long partSize = 50 * 1024 * 1024; //int partCount = (int)fileSize / partSize;
long partCount = fileSize / partSize; //int rest = fileSize % partSize;
long rest = fileSize % partSize; for (int index = 0; index < partCount; index++)
{
byte[] bufferData = new byte[partSize]; fileStream.Read(bufferData, 0, (int)partSize); socketTransmint.Send(bufferData);
}
if (rest != 0)
{
byte[] bufferData = new byte[rest]; fileStream.Read(bufferData, 0, (int)rest); socketTransmint.Send(bufferData);
}
fileStream.Close();
}
}
else
{
MessageBox.Show("对方拒绝了您的发送请求!");
}
}
} //接收文件
private void ReceiveDataListener()
{
this.socketReceiveData.Listen(10); while (true)
{
Socket socketTemp = this.socketReceiveData.Accept();
// byte[] bufferSize = new byte[4];
byte[] bufferSize =new byte[8];
int byteCount = socketTemp.Receive(bufferSize); //int fileSize = BitConverter.ToInt32(bufferSize, 0);
long fileSize = BitConverter.ToInt64(bufferSize, 0); //定义一个已经接收的数据量的变量
//int finishSize = 0;
long finishSize = 0; string fileSavePath = this.txtSaveAs.Text; FileStream fileStream = new FileStream(fileSavePath, FileMode.Create); while (finishSize < fileSize)
{
byte[] bufferData = new byte[8096]; int byteSize = socketTemp.Receive(bufferData); fileStream.Write(bufferData, 0, byteSize); finishSize += byteSize;
}
fileStream.Close();
}
} //文字消息发送
private void btnSend_Click(object sender, EventArgs e)
{
IPEndPoint endPointRemote = new IPEndPoint(IPAddress.Parse(this.txtRemoteIP.Text), int.Parse(this.txtRemoteReceiveMsgPort.Text));
Socket socketClient = new Socket(endPointRemote.AddressFamily, SocketType.Stream, ProtocolType.Tcp); socketClient.Connect(endPointRemote);
if (socketClient.Connected)
{
string message = this.txtMessage.Text;
byte[] buffer = Encoding.Default.GetBytes(message); socketClient.Send(buffer); this.rtbHistory.AppendText(message); this.txtMessage.Text = "";
}
} //发送文件
private void btnBrowser_Click(object sender, EventArgs e)
{
OpenFileDialog openDlg = new OpenFileDialog(); if (DialogResult.OK == openDlg.ShowDialog())
{
this.txtFilePath.Text = openDlg.FileName;
string filePath = this.txtFilePath.Text; string fileName = filePath.Substring(filePath.LastIndexOf(@"\")+1);
string ip = this.localIP.ToString();
string port = this.portResponse.ToString(); string message = string.Format("{0}[fileName]{1}[ip]{2}[port]",fileName,ip,port); byte[] buffer = Encoding.Default.GetBytes(message); IPEndPoint endPointRemote = new IPEndPoint(IPAddress.Parse(this.txtRemoteIP.Text), int.Parse(this.txtRemoteWaitingPort.Text)); Socket socketTemp = new Socket(endPointRemote.AddressFamily, SocketType.Stream, ProtocolType.Tcp); socketTemp.Connect(endPointRemote); if (socketTemp.Connected)
{
socketTemp.Send(buffer);
}
}
} //关闭
private void FormChat_FormClosed(object sender, FormClosedEventArgs e)
{
if (this.socketReceiveMsg != null)
{
this.socketReceiveMsg.Close();
}
if (this.threadReceiveMsg != null)
{
if (this.threadReceiveMsg.IsAlive)
{
this.threadReceiveMsg.Abort();
}
} if (this.socketReceiveData != null)
{
this.socketReceiveData.Close();
}
if (this.threadReceiveData != null)
{
if (this.threadReceiveData.IsAlive)
{
this.threadReceiveData.Abort();
}
} if (this.socketResponse != null)
{
this.socketResponse.Close();
}
if (this.threadResponse != null)
{
if (this.threadResponse.IsAlive)
{
this.threadResponse.Abort();
}
} if (this.socketWaiting != null)
{
this.socketWaiting.Close();
}
if (this.threadWaiting != null)
{
if (this.threadWaiting.IsAlive)
{
this.threadWaiting.Abort();
}
}
}
}
}
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO; namespace SocketTest
{
public partial class FormChat : Form
{
public FormChat()
{
InitializeComponent();
} //声明本机ip
private IPAddress localIP = null; //接收对方信息的socket
private Socket socketReceiveMsg = null;
private int portReceiveMsg;
private Thread threadReceiveMsg = null; //是否接受文件的Socket
private Socket socketWaiting = null;
private int portWaiting;
private Thread threadWaiting = null; //等待对方响应是否接受的socket
private Socket socketResponse = null;
private int portResponse;
private Thread threadResponse = null; //接收文件的Socket
private Socket socketReceiveData;
private int portReceiveData;
private Thread threadReceiveData; private void rtbHistory_Load(object sender, EventArgs e)
{
IPHostEntry hostEntry = Dns.GetHostEntry(Dns.GetHostName());
this.localIP = hostEntry.AddressList[1];
this.txtLocalIP.Text = this.localIP.ToString(); Random random = new Random();
this.portWaiting = random.Next(20000, 30000);
this.portReceiveMsg = random.Next(10000,20000);
this.portReceiveData = random.Next(20000, 40000);
this.portResponse = random.Next(10000,30000);
this.txtLocalReceiveMsgPort.Text = this.portReceiveMsg.ToString();
this.txtLocalWaitingPort.Text = this.portWaiting.ToString(); IPEndPoint endPointReceiveMsg = new IPEndPoint(this.localIP, this.portReceiveMsg);
this.socketReceiveMsg = new Socket(endPointReceiveMsg.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
this.socketReceiveMsg.Bind(endPointReceiveMsg);
this.threadReceiveMsg = new Thread(new ThreadStart(ReceiveMsgListener));
this.threadReceiveMsg.Start(); IPEndPoint endPointWaiting = new IPEndPoint(this.localIP, this.portWaiting);
this.socketWaiting = new Socket(endPointWaiting.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
this.socketWaiting.Bind(endPointWaiting);
this.threadWaiting = new Thread(new ThreadStart(WaitingListener));
this.threadWaiting.Start(); IPEndPoint endPointResponse = new IPEndPoint(this.localIP, this.portResponse);
this.socketResponse = new Socket(endPointResponse.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
this.socketResponse.Bind(endPointResponse);
this.threadResponse = new Thread(new ThreadStart(ResponseListener));
this.threadResponse.Start(); IPEndPoint endPointReceiveData = new IPEndPoint(this.localIP, this.portReceiveData);
this.socketReceiveData = new Socket(endPointReceiveData.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
this.socketReceiveData.Bind(endPointReceiveData);
this.threadReceiveData = new Thread(new ThreadStart(ReceiveDataListener));
this.threadReceiveData.Start();
} private void ReceiveMsgListener()
{
this.socketReceiveMsg.Listen(10); while (true)
{
Socket socketTemp = this.socketReceiveMsg.Accept(); byte[] buffer = new byte[1024];
int byteCount = socketTemp.Receive(buffer); string message = Encoding.Default.GetString(buffer);
this.rtbHistory.AppendText(message);
}
} //等待对方的文件发送请求
private void WaitingListener()
{
this.socketWaiting.Listen(10); while (true)
{
Socket socketTemp = this.socketWaiting.Accept(); this.Invoke(new MyDelegete(SaveShow),socketTemp);
}
} private delegate void MyDelegete(Socket socket); private void SaveShow(Socket socketTemp)
{
byte[] buffer = new byte[1024];
int byteCount = socketTemp.Receive(buffer);
string request = Encoding.Default.GetString(buffer, 0, byteCount); string fileName = request.Substring(0, request.IndexOf("[fileName]"));
string ip = request.Substring(request.IndexOf("[fileName]") + 10, request.IndexOf("[ip]") - (request.IndexOf("[fileName]") + 10));
string port = request.Substring(request.IndexOf("[ip]") + 4, request.IndexOf("[port]") - (request.IndexOf("[ip]") + 4));
int remoteResponsePort = int.Parse(port); SaveFileDialog saveFileDlg = new SaveFileDialog(); saveFileDlg.FileName = fileName; bool isReceive = false; if (saveFileDlg.ShowDialog() == DialogResult.OK)
{
isReceive = true; this.txtSaveAs.Text = saveFileDlg.FileName;
} else
{
isReceive = false;
this.txtSaveAs.Text = "";
}
//向发送方发出回复
IPEndPoint endPointRemote = new IPEndPoint(IPAddress.Parse(this.txtRemoteIP.Text), remoteResponsePort);
Socket socektResponse = new Socket(endPointRemote.AddressFamily, SocketType.Stream, ProtocolType.Tcp); socektResponse.Connect(endPointRemote); if (socektResponse.Connected)
{
string messageResponse = string.Format("{0}[isReceive]{1}[port]",isReceive,this.portReceiveData); byte[] bufferResponse = Encoding.Default.GetBytes(messageResponse); socektResponse.Send(bufferResponse);
}
} //等到接收方的回复
private void ResponseListener()
{
this.socketResponse.Listen(10); while (true)
{
Socket socketTemp = this.socketResponse.Accept(); byte[] buffer = new byte[1024];
int byteCount = socketTemp.Receive(buffer); string messageResponse = Encoding.Default.GetString(buffer, 0, byteCount); bool isReceive = bool.Parse(messageResponse.Substring(0, messageResponse.IndexOf("[isReceive]")));
string portReceiveRemote = messageResponse.Substring(messageResponse.IndexOf("[isReceive]") + 11, messageResponse.IndexOf("[port]") - (messageResponse.IndexOf("[isReceive]") + 11)); if (isReceive)
{
//对方愿意接收文件,准备发送
IPEndPoint endPointRemote = new IPEndPoint(IPAddress.Parse(this.txtRemoteIP.Text), int.Parse(portReceiveRemote));
Socket socketTransmint = new Socket(endPointRemote.AddressFamily, SocketType.Stream, ProtocolType.Tcp); socketTransmint.Connect(endPointRemote); if (socketTransmint.Connected)
{
string filePath = this.txtFilePath.Text; //创建文件流
FileStream fileStream = new FileStream(filePath, FileMode.Open);
//得到文件流的长度
//int fileSize = (int)fileStream.Length;
long fileSize = fileStream.Length;
//先将要发送的文件长度发送给接收方,让对方准备缓冲区
socketTransmint.Send(BitConverter.GetBytes(fileSize));
//定义一个每次要发送的文件的大小(10M)
//int partSize = 10 * 1024 * 1024;
long partSize = 50 * 1024 * 1024; //int partCount = (int)fileSize / partSize;
long partCount = fileSize / partSize; //int rest = fileSize % partSize;
long rest = fileSize % partSize; for (int index = 0; index < partCount; index++)
{
byte[] bufferData = new byte[partSize]; fileStream.Read(bufferData, 0, (int)partSize); socketTransmint.Send(bufferData);
}
if (rest != 0)
{
byte[] bufferData = new byte[rest]; fileStream.Read(bufferData, 0, (int)rest); socketTransmint.Send(bufferData);
}
fileStream.Close();
}
}
else
{
MessageBox.Show("对方拒绝了您的发送请求!");
}
}
} //接收文件
private void ReceiveDataListener()
{
this.socketReceiveData.Listen(10); while (true)
{
Socket socketTemp = this.socketReceiveData.Accept();
// byte[] bufferSize = new byte[4];
byte[] bufferSize =new byte[8];
int byteCount = socketTemp.Receive(bufferSize); //int fileSize = BitConverter.ToInt32(bufferSize, 0);
long fileSize = BitConverter.ToInt64(bufferSize, 0); //定义一个已经接收的数据量的变量
//int finishSize = 0;
long finishSize = 0; string fileSavePath = this.txtSaveAs.Text; FileStream fileStream = new FileStream(fileSavePath, FileMode.Create); while (finishSize < fileSize)
{
byte[] bufferData = new byte[8096]; int byteSize = socketTemp.Receive(bufferData); fileStream.Write(bufferData, 0, byteSize); finishSize += byteSize;
}
fileStream.Close();
}
} //文字消息发送
private void btnSend_Click(object sender, EventArgs e)
{
IPEndPoint endPointRemote = new IPEndPoint(IPAddress.Parse(this.txtRemoteIP.Text), int.Parse(this.txtRemoteReceiveMsgPort.Text));
Socket socketClient = new Socket(endPointRemote.AddressFamily, SocketType.Stream, ProtocolType.Tcp); socketClient.Connect(endPointRemote);
if (socketClient.Connected)
{
string message = this.txtMessage.Text;
byte[] buffer = Encoding.Default.GetBytes(message); socketClient.Send(buffer); this.rtbHistory.AppendText(message); this.txtMessage.Text = "";
}
} //发送文件
private void btnBrowser_Click(object sender, EventArgs e)
{
OpenFileDialog openDlg = new OpenFileDialog(); if (DialogResult.OK == openDlg.ShowDialog())
{
this.txtFilePath.Text = openDlg.FileName;
string filePath = this.txtFilePath.Text; string fileName = filePath.Substring(filePath.LastIndexOf(@"\")+1);
string ip = this.localIP.ToString();
string port = this.portResponse.ToString(); string message = string.Format("{0}[fileName]{1}[ip]{2}[port]",fileName,ip,port); byte[] buffer = Encoding.Default.GetBytes(message); IPEndPoint endPointRemote = new IPEndPoint(IPAddress.Parse(this.txtRemoteIP.Text), int.Parse(this.txtRemoteWaitingPort.Text)); Socket socketTemp = new Socket(endPointRemote.AddressFamily, SocketType.Stream, ProtocolType.Tcp); socketTemp.Connect(endPointRemote); if (socketTemp.Connected)
{
socketTemp.Send(buffer);
}
}
} //关闭
private void FormChat_FormClosed(object sender, FormClosedEventArgs e)
{
if (this.socketReceiveMsg != null)
{
this.socketReceiveMsg.Close();
}
if (this.threadReceiveMsg != null)
{
if (this.threadReceiveMsg.IsAlive)
{
this.threadReceiveMsg.Abort();
}
} if (this.socketReceiveData != null)
{
this.socketReceiveData.Close();
}
if (this.threadReceiveData != null)
{
if (this.threadReceiveData.IsAlive)
{
this.threadReceiveData.Abort();
}
} if (this.socketResponse != null)
{
this.socketResponse.Close();
}
if (this.threadResponse != null)
{
if (this.threadResponse.IsAlive)
{
this.threadResponse.Abort();
}
} if (this.socketWaiting != null)
{
this.socketWaiting.Close();
}
if (this.threadWaiting != null)
{
if (this.threadWaiting.IsAlive)
{
this.threadWaiting.Abort();
}
}
}
}
}
相关阅读 更多 +