使用websocket数据传输传输大量数据时,如何设置才最高效

博客访问: 736707
博文数量: 187
博客积分: 1528
博客等级: 上尉
技术积分: 1777
注册时间:
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: WINDOWS
最近接触到利用socket进行大文件传输的技术,有些心得,与大家分享.首先看看这个过程是怎么进行的(如下图):&&&&所以,我们需要三个socket在窗体加载的时候初始化:1. 等到收货请求的socket(即等待对方向自己发出发送文件的请求:monitorSocket,端口:monitorPort)2. 接收收货方响应的socket(即对方是否愿意接收大文件的回应:responseSocket:端口:responsePort)3. 收货方收货的socket(即接收大文件:receiveSocket:端口:receivePort)&界面的设计如下(由于没有建立服务器,所以在通信时需要首先知道对方的IP和等待请求的端口):&具体步骤:1. 在发送方和接收方的主窗体界面中分别将对方的IP和等待对方发送请求的端口填入;2. Browser_Click(按钮的点击事件),主要完成以下操作:&&& (1)选择要发送的文件,并得到文件名fileN&&& (2)将文件名(fileName),本机IP(localIP)和本机接收对方回应的端口(responsePort)发送给对方的monitorSocket端口3. 接收方接收发送方文件传输请求.在接收方的monitorSocket中完成以下操作:&&& (1)解析出发送方传递的三个信息(fileName,responsePort和monitorSocket)&&& (2)弹出另存为窗口.定义是否接收的变量bool&isReceive =若点击保存,则isReceive=&&& (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 Susing System.Collections.GponentMusing System.Dusing System.Dusing System.Lusing System.Tusing System.Windows.Fusing System.Nusing System.Net.Susing System.Tusing System.IO;namespace SocketTest{&&& public partial class FormChat : Form&&& {&&&&&&& public FormChat()&&&&&&& {&&&&&&&&&&& InitializeComponent();&&&&&&& }&&&&&&& //声明本机ip&&&&&&& private IPAddress localIP =&&&&&&& //接收对方信息的socket&&&&&&& private Socket socketReceiveMsg =&&&&&&& private int portReceiveM&&&&&&& private Thread threadReceiveMsg =&&&&&&& //是否接受文件的Socket&&&&&&& private Socket socketWaiting =&&&&&&& private int portW&&&&&&& private Thread threadWaiting =&&&&&&& //等待对方响应是否接受的socket&&&&&&& private Socket socketResponse =&&&&&&& private int portR&&&&&&& private Thread threadResponse =&&&&&&& //接收文件的Socket&&&&&&& private Socket socketReceiveD&&&&&&& private int portReceiveD&&&&&&& private Thread threadReceiveD&&&&&&& 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(2);&&&&&&&&&&& this.portReceiveMsg = random.Next();&&&&&&&&&&& this.portReceiveData = random.Next(2);&&&&&&&&&&& this.portResponse = random.Next();&&&&&&&&&&& 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 = fileN&&&&&&&&&&& bool isReceive =&&&&&&&&&&& if (saveFileDlg.ShowDialog() == DialogResult.OK)&&&&&&&&&&& {&&&&&&&&&&&&&&& isReceive =&&&&&&&&&&&&&&& this.txtSaveAs.Text = saveFileDlg.FileN&&&&&&&&&&& }&&&&&&&&&&& else&&&&&&&&&&& {&&&&&&&&&&&&&&& isReceive =&&&&&&&&&&&&&&& 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.T&&&&&&&&&&&&&&&&&&&&&&& //创建文件流&&&&&&&&&&&&&&&&&&&&&&& FileStream fileStream = new FileStream(filePath, FileMode.Open);&&&&&&&&&&&&&&&&&&&&&&& //得到文件流的长度&&&&&&&&&&&&&&&&&&&&&&& //int fileSize = (int)fileStream.L&&&&&&&&&&&&&&&&&&&&&&& long fileSize = fileStream.L&&&&&&&&&&&&&&&&&&&&&&& //先将要发送的文件长度发送给接收方,让对方准备缓冲区&&&&&&&&&&&&&&&&&&&&&&& socketTransmint.Send(BitConverter.GetBytes(fileSize));&&&&&&&&&&&&&&&&&&&&&&& //定义一个每次要发送的文件的大小(10M)&&&&&&&&&&&&&&&&&&&&&&& //int partSize = 10 * 1024 * 1024;&&&&&&&&&&&&&&&&&&&&&&& long partSize = 50 * 1024 * 1024;&&&&&&&&&&&&&&&&&&&&&&& //int partCount = (int)fileSize / partS&&&&&&&&&&&&&&&&&&&&&&& long partCount = fileSize / partS&&&&&&&&&&&&&&&&&&&&&&& //int rest = fileSize % partS&&&&&&&&&&&&&&&&&&&&&&& long rest = fileSize % partS&&&&&&&&&&&&&&&&&&&&&&& for (int index = 0; index < partC 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.T&&&&&&&&&&&&&&& 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 += byteS&&&&&&&&&&&&&&& }&&&&&&&&&&&&&&& 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.T&&&&&&&&&&&&&&& 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.FileN&&&&&&&&&&&&&&& string filePath = this.txtFilePath.T&&&&&&&&&&&&&&& 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();&&&&&&&&&&&&&&& }&&&&&&&&&&& }&&&&&&& }&&& }}
阅读(27020) | 评论(0) | 转发(0) |
相关热门文章
给主人留下些什么吧!~~
请登录后评论。> 博客详情
既然是Socket
那就是传2进制的数据 也就是字节数组 使用 某种网络协议,点对点的传输数据。
提高的效率可以分为三部分!
1. 网络情况。
下哔片什么的我们这里不讨论,但是首先你要明确你的网络类型,你的带宽允许你多大的传输量才好写程序。网卡我们暂时不讨论。
2. 服务器情况。
国内的网络运营商都会 限制很多机房服务器的上传限额。下行200k 上行可能只有20k。也就是1:10 你网络没问题程序没问题,服务器不吃,也没办法! 所以这个也要解决。
3 如果上面两个都不是问题,那就完全是程序方面的了,我们开始讨论。
假设你需要制作一个提供至少1G 的单体文件上传,你会怎么办。我想你绝对不会 搞一个线程 慢慢读过去。
为什么? 因为如果断网,死机,或者停电,你又要从头来。
所以 效率这个概念既然提出来了就不光是速度问题。还有实用性的问题。但是我们不上升到一个完整的下载上传软件的高度。
所以你可以看到以下的概念:
(1). 将你的文件包分割成数据模型,并以一个配置文档描述。这个文档可以很小 1G的文件几k足以。
(2) 根据分割情况开启数个线程,根据你的网络情况去调整你的每一传输线程里的 byte数组大小。
(3) 控制好线程管理, 如果这个程序能独享一台电脑的话 就全部全力工作。
首先接收到你的说明文件 ,然后根据情况开启接受程序,并按照你的说明文件,将每个线程里的数据重构到一个临时文件里。并且开始重写说明文件,介绍各个情况的进度,与位置。
于是 一个简单的断点续传就这么出来了。
传输效率这是个很大的命题,算法是一部分,形式是一部分,网络是最重要的一部分。
人打赏支持
码字总数 3678
支付宝支付
微信扫码支付
打赏金额: ¥
已支付成功
打赏金额: ¥

我要回帖

更多关于 java socket 数据传输 的文章

 

随机推荐