[原创] 使用Tcp/Ip下载文件(图)
作者:C/S框架网  发布日期:2011/07/16 00:26:43
  [原创] 使用Tcp/Ip下载文件(图)

[原创] 使用Tcp/Ip下载文件(图)


使用Tcp/Ip下载文件(图)


简单设计思路是在服务器端启动TcpListener监听客户端的Socket连接。
当Client发送连接请求,TcpListener捕获当前请求的Socket,并获取收到的数据(字符串,称为命令)。
然后由命令处理程序分析字符串,如果字符串头部包含GET_FILE则为下载文件请求。


例:如客户机向服务器程序发送请求:"GET_FILE|D:\PUBLISH\TEST.DLL"。首先TcpListener捕获
当前请求的Socket,收到字符串,如果是下载文件请求就通过socket.SendFile(file="D:\PUBLISH\
TEST.DLL")将文件传送给当前Socket。在客户端由NetworkStream.Read()方法接收来自服务器发送的文件。

同理,如果实现网上象棋对战游戏,通过Socket.Send(命令)->分析->执行->移动棋子,不就实现了吗?

Socket应用往往不止这些,学会Socket组件是网络编程基础。





服务器界面运行图。

贴图图片


客户机界面截图:

贴图图片

输入要下载的文件名及保存目录。



思考:

1.如果提供一个下载文件清单,是不是可以批量下载文件?
2.如果服务器上的文件与本机的文件最后修改日期相比较,是不是可以改装为版本升级程序?
3.如果客户端向服务器上传文件,是不是可以改装成mini版的ftp程序?
4.如果收到的byte[]是某对象的序列化数据,而后将byte[]还原成对象,是不是实现tcp/ip传送对象?
5.如果对象是一个电脑向另一个电脑传送的某个命令,是不是可以实现网上对战游戏?
6.你思想有多远socket就能走多远。



部分原代码:

UpgraderClient.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.IO;

namespace VJSDN.Tech.TcpIpDownloader
{
   /// <summary>
   /// Tcp/ip下载器客户端
   /// </summary>
   public class UpgraderClient
   {
      private OutputInvoke _writeOutput = null;
      
      public UpgraderClient(OutputInvoke writeOutput)
      {
         _writeOutput = writeOutput;
      }
      
      /// <summary>
      /// 下载文件
      /// </summary>
      public bool DownloadFile(string file, string savePath)
      {
         string hostIp = "8.8.8.2"; //主机ip
         int hostPort = 12346; //主机端口
         
         try
         {
            TcpClient client = new TcpClient();
            client.ReceiveTimeout = 1000 * 60;
            
            if (client == null || file.Trim() == "") return false;
            
            TryConnect(client, hostIp, hostPort); //连接服务器
            if (!client.Connected) return false;//连线线失败,退出
            
            byte[] bs = Encoding.Unicode.GetBytes("GET_FILE|" + file);
            client.Client.Send(bs); //发送请求
            
            //开始接受数据....
            NetworkStream ns = client.GetStream();
            MemoryStream ms = new System.IO.MemoryStream();
            
            byte[] resBytes = new byte[256];
            int resSize;
            do
            {
               resSize = ns.Read(resBytes, 0, resBytes.Length);
               string msg = Byte2Str(resBytes);
               if (msg.Trim().ToUpper() == "FILE_NOT_FOUND")
               {
                  if (_writeOutput != null) _writeOutput("找不到文件:" + file);
                  break;
               }
               if (resSize == 0) break;
               
               ms.Write(resBytes, 0, resSize);
               } while (ns.DataAvailable);
               
               if (ms.Length > 0)
               {
                  FileStream fs = File.Open(savePath, FileMode.OpenOrCreate, FileAccess.Write);
                  fs.Write(ms.ToArray(), 0, (int)ms.Length);
                  fs.Flush();
                  fs.Close(); //关闭文件流
                  if (_writeOutput != null) _writeOutput("文件已下载:" + file);
               }
               
               ms.Close(); //关闭内存流
               client.Close();
               return true;
            }
            catch
            {
               return false;
            }
         }
         
         private string Byte2Str(byte[] buffer)
         {
            string msg = Encoding.Unicode.GetString(buffer).Replace("\0", "");
            return msg.Trim();
         }
         
         private void TryConnect(TcpClient client, string hostIP, int hostPort)
         {
            try
            {
               client.Connect(IPAddress.Parse(hostIP), hostPort); //连接服务器
            }
            catch
            {
               throw new Exception("主机已关闭或网络存在问题,不能建立连线!");
            }
         }
      }
   }
   
   

UpgraderServer.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using System.Windows.Forms;
using System.IO;

namespace VJSDN.Tech.TcpIpDownloader
{
   public delegate void OutputInvoke(string msg);
   
   public class UpgraderServer
   {
      private TcpListener _ServerListener = null; //本地监听 
      private Thread _ServerListenerThread = null; //监听使用的线程
      private bool _ServerRunning = false;
      
      private Form _owner = null;
      private OutputInvoke _writeOutput = null;
      
      public UpgraderServer(Form owner, OutputInvoke method)
      {
         _owner = owner;
         _writeOutput = method;
      }
      
      //启动服务器程序. 参数说明 ip:本地消息服务器IP地址; port:端口
      public void StartListening(string ip, int port)
      {
         if (_ServerRunning) return;
         
         //构建监听
         _ServerListener = new TcpListener(IPAddress.Parse(ip), port);
         _ServerListener.Start(255);
         _ServerRunning = true;
         
         //启动线程
         _ServerListenerThread = new Thread(new ThreadStart(DoStartServerListener));
         _ServerListenerThread.IsBackground = true;
         _ServerListenerThread.Start();
      }
      
      //关闭服务器程序.
      public void Stop()
      {
         _ServerRunning = false;
         _ServerListenerThread.Abort(101);
         _ServerListenerThread = null;
         _ServerListener.Stop();
      }
      
      /// <summary>
      ///启动服务器程序.
      /// </summary>
      private void DoStartServerListener()
      {
         //监听客户连线请求
         while (_ServerRunning)
         {
            try
            {
               if (_ServerListener == null) return; //防止其它地方关闭监听 
               Application.DoEvents();
               Socket socket = _ServerListener.AcceptSocket(); //有客户请求连接
               if (socket == null) continue;
               
               byte[] buffer = new Byte[socket.ReceiveBufferSize];
               int i = socket.Receive(buffer); //接收请求数据.
               if (i <= 0) continue;
               
               string msg = Encoding.Unicode.GetString(buffer).Replace("\0", "");
               msg = msg.Trim();
               if (msg.ToUpper().StartsWith("GET_FILE")) //命令字符串:GET_FILE|.\a.dll
               {
                  string[] sps = msg.Split(new char[] { char.Parse("|") });
                  string file = sps[1]; //取出文件a.dll
                  this.SendFile(socket, file);
               }
               socket.Close();//
            }
            catch (Exception ex)
            {
               if (ex is ThreadAbortException)
               {
                  if ((ex as ThreadAbortException).ExceptionState.ToString() == "101")
                  {
                     _ServerRunning = false;
                     ShowMessage("用户关闭服务器.");
                  }
                  else
                  ShowMessage(ex.Message);
               }
               else
               {
                  ShowMessage(ex.Message);
               }
            }
         }
      }
      
      private void ShowMessage(string msg)
      {
         _owner.Invoke(this._writeOutput,msg);
      }
      
      private void SendFile(Socket socket, string file)
      {
         if (File.Exists(file))
         {
            ShowMessage("获取文件[" + file + "]....");
            socket.SendFile(file);
            ShowMessage("[" + file + "]已发送.");
         }
         else
         {
            socket.Send(Encoding.Unicode.GetBytes("FILE_NOT_FOUND")); //通知客户程序
            ShowMessage("[" + file + "]不存在.");
         }
      }
   }
}



服务器界面代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using VJSDN.Tech.TcpIpDownloader;

namespace VJSDN.Tech.TcpIpDownloaderServer
{
   public partial class frmUpgraderServer : Form
   {
      private UpgraderServer _UpgradeListener = null;
      
      public frmUpgraderServer()
      {
         InitializeComponent();
      }
      
      private void frmUpgraderServer_Load(object sender, EventArgs e)
      {
         //
      }
      
      private void btnStart_Click(object sender, EventArgs e)
      {
         string hostIp = "8.8.8.2";
         int hostPort = 12346;
         
         _UpgradeListener = new UpgraderServer(this, this.Output);
         _UpgradeListener.StartListening(hostIp, hostPort);
         listBox1.Items.Add("已启动服务.");
      }
      
      private void btnStop_Click(object sender, EventArgs e)
      {
         if (_UpgradeListener != null)
         {
            _UpgradeListener.Stop();
            _UpgradeListener = null;
            listBox1.Items.Add("已关闭服务.");
         }
      }
      
      public void Output(string msg)
      {
         this.listBox1.Items.Add(msg);
      }
      
      private void frmUpgraderServer_FormClosing(object sender, FormClosingEventArgs e)
      {
         if (_UpgradeListener != null) _UpgradeListener.Stop();
      }
   }
}


下载窗体代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using VJSDN.Tech.TcpIpDownloader;
using System.IO;

namespace TestProject
{
   public partial class frmDownloader : Form
   {
      public frmDownloader()
      {
         InitializeComponent();
      }
      
      private void button1_Click(object sender, EventArgs e)
      {
         string filename = Path.GetFileName(textBox1.Text);
         string local = textBox2.Text + @"\" + filename;
         bool ret = new UpgraderClient(this.ShowOutput).DownloadFile(textBox1.Text, local);
         if (ret)
         MessageBox.Show("下载完成!");
         else
         MessageBox.Show("下载失败!");
      }
      
      private void ShowOutput(string msg)
      {
         MessageBox.Show(msg);
      }
   }
}


附完整源代码。解压后加载客户测试窗体到项目工程。



C/S框架网|原创精神.创造价值.打造精品


扫一扫加作者微信
C/S框架网作者微信 C/S框架网|原创作品.质量保障.竭诚为您服务

点击下载附件 点击下载附件 (如下载失败,请邮件通知我们寄回给您,或QQ:23404761留言.)
上一篇 下一篇