C# tcp发送消息和传输文件

本文介绍了一种使用TCP点对点传输实现服务器文件双机备份的方法。通过FileSystemWatcher监控文件变化,并利用自定义TcpHelper类库进行文件同步。该方案包括文件发送、接收及校验等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【背景】

     最近做了一个双机备份,就是服务器上有个文件夹,会接收客户端传来的文件,而我们要做的就是同步这台服务器和另一台备用服务器上的文件.

     为了实现这个功能我们使用的tcp点对点传输.

【开发环境】

     VS2005

【实现原理】

     要实现同步要解决两个问题,一个是获取本地服务器上上传上来的文件,二是实现两台机器间的文件传输.

     第一个问题我们用的FileSystemWatcher这个可以监视指定文件夹下的文件变动,然后我们把变动的文件信息记录到数据库,在指定的时间间隔后同步两台机器的文件.

     第二个问题我们用的tcp文件传输,我们按照一定的原则通过传输消息来告知备份服务器的要传输的文件名称和大小,然后传输文件.

【代码】

     1:FileSystemWatcher监视文件变动的就不介绍了,很简单的winform控件应用.

     2:为了完成文件传输,我做了一个TcpHelper类库,其中包括TcpCommon,TcpClientHelper,TcpListenerHelper三个类,TcpCommon主要实现了文件传输时用的一些公共的方法比如发送接收文件,发送接收消息,和文件hash的计算

TcpCommon

ContractedBlock.gif ExpandedBlockStart.gif Code
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.IO;
using System.Net.Sockets;

namespace Xpwy.Backup.PTcpHelper
{
    
internal class TcpCommon
    {
        
private static readonly int _blockLength = 500 * 1024;

        
/// <summary>
        
/// 计算文件的hash值 
        
/// </summary>
        internal string CalcFileHash(string FilePath)
        {
            MD5CryptoServiceProvider md5 
= new MD5CryptoServiceProvider();
            
byte[] hash;
            
using (FileStream fs = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096))
            {
                hash 
= md5.ComputeHash(fs);
            }
            
return BitConverter.ToString(hash);
        }

        
/// <summary>
        
/// 发送文件
        
/// </summary>
        
/// <param name="filePath"></param>
        
/// <param name="stream"></param>
        
/// <returns></returns>
        internal bool SendFile(string filePath, NetworkStream stream)
        {
            FileStream fs 
= File.Open(filePath, FileMode.Open);
            
int readLength = 0;
            
byte[] data = new byte[_blockLength];

            
//发送大小
            byte[] length = new byte[8];
            BitConverter.GetBytes(
new FileInfo(filePath).Length).CopyTo(length, 0);
            stream.Write(length, 
08);

            
//发送文件
            while ((readLength = fs.Read(data, 0, _blockLength)) > 0)
            {
                stream.Write(data, 
0, readLength);
            }
            fs.Close();
            
return true;
        }

        
/// <summary>
        
/// 接收文件
        
/// </summary>
        
/// <param name="filePath"></param>
        
/// <param name="stream"></param>
        
/// <returns></returns>
        internal bool ReceiveFile(string filePath, NetworkStream stream)
        {
            
try
            {
                
long count = GetSize(stream);
                
if (count == 0)
                {
                    
return false;
                }

                
long index = 0;
                
byte[] clientData = new byte[_blockLength];
                
if (File.Exists(filePath))
                {
                    File.Delete(filePath);
                }
                
string path=new FileInfo(filePath).Directory.FullName;
                
if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }

                FileStream fs 
= File.Open(filePath, FileMode.OpenOrCreate);
                
try
                {                    
                    
//计算当前要读取的块的大小
                    int currentBlockLength = 0;
                    
if (_blockLength < count - index)
                    {
                        currentBlockLength 
= _blockLength;
                    }
                    
else
                    {
                        currentBlockLength 
=(int)( count - index);
                    }

                    
int receivedBytesLen = stream.Read(clientData, 0, currentBlockLength);
                    index 
+= receivedBytesLen;
                    fs.Write(clientData, 
0, receivedBytesLen);

                    
while (receivedBytesLen > 0 && index < count)
                    {
                        clientData 
= new byte[_blockLength];
                        receivedBytesLen 
= 0;

                        
if (_blockLength < count - index)
                        {
                            currentBlockLength 
= _blockLength;
                        }
                        
else
                        {
                            currentBlockLength 
= (int)(count - index);
                        }
                        receivedBytesLen 
= stream.Read(clientData, 0, currentBlockLength);
                        index 
+= receivedBytesLen;
                        fs.Write(clientData, 
0, receivedBytesLen);
                    }
                }
                
catch (Exception ex)
                {
                    
return false;
                }
                
finally
                {
                    fs.Close();
                }
            }
            
catch (Exception ex)
            {
                
return false;
            }
            
return true;
        }

        
/// <summary>
        
/// 发送消息
        
/// </summary>
        
/// <param name="message"></param>
        
/// <param name="stream"></param>
        
/// <returns></returns>
        internal bool SendMessage(string message, NetworkStream stream)
        {

            
byte[] data = Encoding.UTF8.GetBytes(message);
            
byte[] resultData = new byte[8 + data.Length];
            BitConverter.GetBytes(data.Length).CopyTo(resultData, 
0);
            data.CopyTo(resultData, 
8);

            stream.Write(resultData, 
0, resultData.Length);
            
return true;
        }

        
/// <summary>
        
/// 读取消息
        
/// </summary>
        
/// <param name="stream"></param>
        
/// <returns></returns>
        internal string ReadMessage(NetworkStream stream)
        {
            
string result = "";
            
int messageLength = 0;

            
byte[] resultbyte = new byte[500 * 1024];
            
//读取数据大小
            int index = 0;
            
int count = GetSize(stream);

            
byte[] data = new byte[count];
            
while (index < count && (messageLength = stream.Read(data, 0, count - index)) != 0)
            {
                data.CopyTo(resultbyte, index);
                index 
+= messageLength;
            }
            result 
= Encoding.UTF8.GetString(resultbyte, 0, index);
            
return result;
        }

        
/// <summary>
        
/// 获取要读取的数据的大小
        
/// </summary>
        
/// <param name="stream"></param>
        
/// <returns></returns>
        private int GetSize(NetworkStream stream)
        {
            
int count = 0;
            
byte[] countBytes = new byte[8];
            
try
            {
                
if (stream.Read(countBytes, 08== 8)
                {
                    count 
= BitConverter.ToInt32(countBytes, 0);
                }
                
else
                {
                    
return 0;
                }
            }
            
catch (Exception ex)
            {

            }
            
return count;
        }
    }
}

TcpClientHelper

ContractedBlock.gif ExpandedBlockStart.gif Code
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;

namespace Xpwy.Backup.PTcpHelper
{
    
public class TcpClientHelper:IDisposable
    {
        TcpClient client;
        NetworkStream netstream;
        
string _serverip = "127.0.0.1";
        
int _port = 8080;

        TcpCommon tcpCommon 
= new TcpCommon();

        
#region TcpClientHelper constructor
        
public TcpClientHelper(string strServerIP, int serverPort)
        {
            _serverip 
= strServerIP;
            _port 
= serverPort;

        }
        
#endregion

        
public void Start()
        {
            client 
= new TcpClient(_serverip, _port);
            netstream 
= client.GetStream();
        }

        
public void Stop()
        {
            
if (netstream != null)
            {
                netstream.Close();
            }

            
if (client != null)
            {
                client.Close();
            }
        }

        
#region TcpCommon所有方法
        
public string CalcFileHash(string FilePath)
        {
            
return tcpCommon.CalcFileHash(FilePath);
        }

        
public bool SendFile(string filePath)
        {
            
return tcpCommon.SendFile(filePath, netstream);
        }


        
public bool ReceiveFile(string filePath)
        {
            
return tcpCommon.ReceiveFile(filePath, netstream);
        }


        
public bool SendMessage(string message)
        {
            
return tcpCommon.SendMessage(message, netstream);
        }

        
public string ReadMessage()
        {
            
return tcpCommon.ReadMessage(netstream);
        }
        
#endregion

        
#region IDisposable 成员

        
public void Dispose()
        {
            
if (netstream != null)
            {
                netstream.Close();
            }

            
if (client != null)
            {
                client.Close();
            }
        }

        
#endregion
    }
}

TcpListenerHelper

ContractedBlock.gif ExpandedBlockStart.gif Code
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;

namespace Xpwy.Backup.PTcpHelper
{
    
public class TcpListenerHelper
    {
        
private string _strServerIP = "";
        
private int _serverPort = 0;

        TcpListener server;
        TcpClient client;
        NetworkStream netstream;
        IAsyncResult asyncResult;
        TcpCommon tcpCommon 
= new TcpCommon();

        ManualResetEvent listenConnected 
= new ManualResetEvent(false);

        
bool _active = false;

        
public TcpListenerHelper(string strServerIP, int serverPort)
        {
            _strServerIP 
= strServerIP;
            _serverPort 
= serverPort;
            server 
= new TcpListener(IPAddress.Parse(strServerIP), serverPort);
            server.Server.ReceiveTimeout 
= 6000;
            server.Server.SendTimeout 
= 6000;
        }

        
/// <summary>
        
/// 启动
        
/// </summary>
        public void Start()
        {
            
try
            {
                _active 
= true;
                server.Start();
            }
            
catch (Exception ex)
            {
                
throw ex;
            }
        }

        
/// <summary>
        
/// 停止
        
/// </summary>
        public void Stop()
        {
            
try
            {
                _active 
= false;
                
if (client != null)
                {
                    client.Close();
                }

                
if (netstream != null)
                {
                    netstream.Close();
                }
                server.Stop();
                
            }
            
catch (Exception ex)
            {
                
throw ex;
            }
        }

        
public void Listen()
        {
            listenConnected.Reset();
            asyncResult 
= server.BeginAcceptTcpClient(new AsyncCallback(AsyncCall), server);
        }

        
public void AsyncCall(IAsyncResult ar)
        {
            
try
            {
                TcpListener tlistener 
= (TcpListener)ar.AsyncState;

                
if (_active)
                {
                    client 
= tlistener.EndAcceptTcpClient(ar);
                    netstream 
= client.GetStream();
                }
                
else
                {
                    client 
= null;
                    netstream 
= null;
                }
                listenConnected.Set();
            }
            
catch (Exception ex)
            {
                
throw ex;
            }
        }
        
public bool WaitForConnect()
        {
            listenConnected.WaitOne();

            
if (client != null && netstream != null)
            {
                
return true;
            }
            
else
            {
                
return false;
            }
        }
        

        
#region TcpCommon所有方法
        
/// <summary>
        
/// 计算文件的hash值 
        
/// </summary>
        public string CalcFileHash(string FilePath)
        {
            
return tcpCommon.CalcFileHash(FilePath);
        }

        
/// <summary>
        
/// 发送文件
        
/// </summary>
        
/// <param name="filePath"></param>
        
/// <returns></returns>
        public bool SendFile(string filePath)
        {
            
return tcpCommon.SendFile(filePath, netstream);
        }

        
/// <summary>
        
/// 接收文件
        
/// </summary>
        
/// <param name="filePath"></param>
        
/// <returns></returns>
        public bool ReceiveFile(string filePath)
        {
            
return tcpCommon.ReceiveFile(filePath, netstream);
        }

        
/// <summary>
        
/// 发送消息
        
/// </summary>
        
/// <param name="message"></param>
        
/// <returns></returns>
        public bool SendMessage(string message)
        {
            
return tcpCommon.SendMessage(message, netstream);
        }

        
/// <summary>
        
/// 接收消息
        
/// </summary>
        
/// <returns></returns>
        public string ReadMessage()
        {
            
return tcpCommon.ReadMessage(netstream);
        }
        
#endregion

        
#region IDisposable 成员

        
public void Dispose()
        {
            Stop();
        }

        
#endregion
    }
}

 

      3:调用的代码

server端:

 

ContractedBlock.gif ExpandedBlockStart.gif Code
public void DoWork(object state)
        {
            TcpListenerHelper tlistener 
= (TcpListenerHelper)state;
            tlistener.Listen();
//监听

            
while (tlistener.WaitForConnect())//等待知道监听到了连接
            {
                
try
                {
                    
string firstMessage = "";
                    
while (!string.IsNullOrEmpty((firstMessage = tlistener.ReadMessage())))
                    {
                        
if (firstMessage.ToLower() == "filebak".ToLower())
                        {
                            tlistener.SendMessage(
"filebakok");
                            
#region 文件备份
                            
string filepath = Path.Combine(Environment.CurrentDirectory, "FileBak\\" + tlistener.ReadMessage()).ToString();
                            tlistener.ReceiveFile(filepath);
                            
if (tlistener.CalcFileHash(filepath) == tlistener.ReadMessage())
                            {
                                tlistener.SendMessage(
"ok");
                            }
                            
else
                            {
                                tlistener.SendMessage(
"wrong");
                            }
                            
#endregion
                        }
                        
else if (firstMessage.ToLower() == "DBBak".ToLower())
                        {
                            
#region 数据库备份
                            tlistener.SendMessage(
"dbbakok");
                            
string filename = tlistener.ReadMessage();
                            
string filepath = Path.Combine(System.Environment.CurrentDirectory, "DBBak"+"\\"+ filename;
                            
//接收文件
                            tlistener.ReceiveFile(filepath);
                            
//验证hash值
                            string hash = tlistener.ReadMessage();
                            
if (hash == tlistener.CalcFileHash(filepath))
                                tlistener.SendMessage(
"ok");
                            
else
                                tlistener.SendMessage(
"wrong");

                            
#endregion
                        }
                    }
                }
                
catch
                {
                }

                tlistener.Listen();
//监听下一个连接
            }
        }

client端:

 

ContractedBlock.gif ExpandedBlockStart.gif Code
private void FileBackup(object arg)
        {
            TcpClientHelper client 
= (TcpClientHelper)arg;

            
//获取需备份的文件
            DataTable dt = this._oFileWatch.GetBackupFiles();

            
if (dt != null)
            {
                
for (int i = 0; i < dt.Rows.Count; i++)
                {
                    client.SendMessage(
"FileBak");

                    
if (client.ReadMessage().ToLower() == "filebakok")
                    {
                        client.SendMessage(dt.Rows[i][
"RelativePath"].ToString());
                        client.SendFile(dt.Rows[i][
"FullPath"].ToString());
                        client.SendMessage(client.CalcFileHash(dt.Rows[i][
"FullPath"].ToString()));

                        
if (client.ReadMessage().ToLower() == "ok")
                        {
                            LOGClass.WriteLog(
"备份文件【" + dt.Rows[i]["FullPath"].ToString() + "】成功");
                        }
                        
else
                        {
                            LOGClass.WriteLog(
"备份文件【" + dt.Rows[i]["FullPath"].ToString() + "】失败。");
                        }
                    }
                }

                
this._oFileWatch.ClearTmp();
            }
        }

 

【TcpHelper代码】

 /Files/zrx401558287/PTcpHelper.rar

转载于:https://www.cnblogs.com/zrx401558287/archive/2009/03/13/1410871.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值