C # using FileSystemWatcher to monitor a specified folder, and use the TCP / IP protocol to send to another specified folder by Socket

Project requirements:

There are two computers, computer A (Windows systems) LAN is mainly responsible for receiving files (Remote Desktop paste, FTP upload, shared folders, etc.), hope can be automatically transferred to the computer B (Windows system) after receiving the file A to do a backup, there is a directory on the computer B, if the paste files into this directory, and will be automatically transferred to the a to save.

So by Baidu found System.IO.FileSystemWatcher this category, some messages through which to monitor a specified folder (file creation, file modify, delete files, rename the file) do the corresponding action, currently only needs to monitor file creation other events not to deal with.

File transfer, you can write your own on Socket Server and Client, but pay attention to the problem of stick package. I'm here uses the open source NewLife.Net (https://github.com/NewLifeX/NewLife.Net), the client and server are using it, then stick package built solutions to solve the problem, but it is very easy to manage, It comes with a powerful log output. Here to share code to achieve as well as some problems.

1, create a Winform project, operational framework for .Netframework4.6

References NewLife.Net on Nuget 

Interface structure is as follows:

 

The local port, on behalf of the machine as a server (server) listening port, the remote server IP and port when the unit is monitoring the file is created, which is automatically sent to the server (receiving server also need to run the software).

Local monitoring automatically sent folder: Those who are sent automatically go in the specified folder in a new (usually paste) files are.

Automatically saved received folder: all files sent from a remote, are automatically saved in this folder.

2, implementation code

Program.cs defined two global variables used to save folder information

/// <Summary> 
/// to monitor the received save folder 
/// </ Summary> 
public static String the SaveDir = ""; 
 
/// <Summary> 
/// folders to monitor transmission 
/// < / Summary> 
public static String SendDir = "";

Some classes using the

using System;
using System.Data;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using DirectoryWatch.Class;
using NewLife.Data;
using NewLife.Log;
using NewLife.Net;
using NewLife.Net.Handlers;

When the form is loaded, the common variables and defining some form specified below for the log output vector TextBox

private static int remotePort = 0; // remote port 
private static int localPort = 0; // local port 
private static string remoteIP = ""; // remote IP 
Private FileSystemWatcher Watcher; // monitor a folder 
private NetServer server; // local service 
Private void MainFrm_Load (SENDER Object, EventArgs E) 
{ 
   textBox1.UseWinFormControl (); 
}

Local monitoring folder selection button code

void Btn_dirbd_Click Private (SENDER Object, EventArgs E) 
{ 
    the using (var folderBrowser the FolderBrowserDialog new new = ()) 
    { 
        IF (! folderBrowser.ShowDialog () = DialogResult.OK) return; 
        Program.SendDir = folderBrowser.SelectedPath; 
        IF (Directory!. eXISTS (Program.SendDir)) 
        { 
            MessageBox.Show (@ "selected path does not exist or does not have access," @ "error", MessageBoxButtons.OK, MessageBoxIcon.Error); 
            return; 
        } 
        IF (String.equals (Program. SaveDir.ToLower (), Program.SendDir.ToLower ())) 
        { 
            MessageBox.Show (@ "automatic reception folder and folders can not be automatically sent a same folder" @ "error", MessageBoxButtons.OK, MessageBoxIcon. Error); 
            return; 
        }
        txt_localPath.Text = folderBrowser.SelectedPath;
        Program.SendDir = folderBrowser.SelectedPath;
    }
}

Local automatically saved folder selection button code

void Btn_saveDic_Click Private (SENDER Object, EventArgs E) 
{ 
    the using (var folderBrowser the FolderBrowserDialog new new = ()) 
    { 
        IF (! folderBrowser.ShowDialog () = DialogResult.OK) return; 
        Program.SaveDir = folderBrowser.SelectedPath; 
        IF (Directory!. eXISTS (Program.SendDir)) 
        { 
            MessageBox.Show (@ "selected path does not exist or does not have access," @ "error", MessageBoxButtons.OK, MessageBoxIcon.Error); 
            return; 
        } 
        IF (String.equals (Program. SaveDir.ToLower (), Program.SendDir.ToLower ())) 
        { 
            MessageBox.Show (@ "automatic reception folder and folders can not be automatically sent a same folder" @ "error", MessageBoxButtons.OK, MessageBoxIcon. Error);  
            return;
        }
        txt_remoteDir.Text = folderBrowser.SelectedPath;
        Program.SaveDir = folderBrowser.SelectedPath;
    }
}

Startup Code (start local monitoring, enable the local SocketServer Service)

void Btn_Start_Click Private (SENDER Object, EventArgs E) 
{ 
    int.TryParse (txt_remotePort.Text, remotePort OUT); 
    int.TryParse (txt_localPort.Text, localPort is OUT); 
    IF (String.IsNullOrEmpty (txt_remoteIP.Text.Trim ())) 
    { 
        MessageBox.Show (@ "Please fill in the remote server IP", @ "error", MessageBoxButtons.OK, MessageBoxIcon.Error); 
        return; 
    } 
    remoteip txt_remoteIP.Text.Trim = (); 
    IF (remotePort == 0) 
    { 
        the MessageBox .Show (@ "please fill out the remote server's port", @ "error", MessageBoxButtons.OK, MessageBoxIcon.Error); 
        return; 
    } 
    IF (localPort == 0) 
    {
        MessageBox.Show (@ "Please fill port on the local server to open the" @ "error", MessageBoxButtons.OK, MessageBoxIcon.Error); 
        return; 
    } 
 
    IF (String.IsNullOrEmpty (Program.SendDir)) 
    { 
        MessageBox.Show (@ "Please select automatic transmission local folder path", @ "error", MessageBoxButtons.OK, MessageBoxIcon.Error); 
        return; 
    } 
    IF (String.IsNullOrEmpty (Program.SaveDir)) 
    { 
        MessageBox.Show (@ "Please select local automatic file folder path transmission and reception over the "@" error ", MessageBoxButtons.OK, MessageBoxIcon.Error); 
        return; 
    } 
    IF (Btn_Start.Text.Equals (" stop ")) 
    { 
        watcher.EnableRaisingEvents = to false; 
        server.Stop ( "manual stop");
        Btn_Start.Text = @ "start";
        foreach (Control control in Controls)
        { 
            IF (!! (The Button Control IS) && (the TextBox Control IS)) Continue; 
            IF (Control.Name = "Btn_Start"!) 
            { 
                Control.Enabled = to true; 
            } 
        } 
        return; 
    } 
    Watcher the FileSystemWatcher new new = 
    { 
        the Path = Program .SendDir, 
        the Filter =. "* *" // monitors all file 
    }; 
    watcher.Created + = OnProcess; // add only monitors file 
    //watcher.Changed + = OnProcess; 
    //watcher.Deleted new new FileSystemEventHandler + = ( OnProcess); 
    //watcher.Renamed += new RenamedEventHandler(OnRenamed);
    watcher.EnableRaisingEvents = to true; // whether to allow monitoring events to take effect
    = NotifyFilters.Attributes //watcher.NotifyFilter | NotifyFilters.CreationTime | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.Security | NotifyFilters.Size; 
    watcher.NotifyFilter = NotifyFilters.FileName; // this is Some notification properties currently do not 
    watcher.IncludeSubdirectories = true; // contains a subfolder 
 
    Server NetServer new new = 
    { 
        the Log = XTrace.Log, 
        SessionLog = XTrace.Log, 
        SocketLog = XTrace.Log, 
        Port = localPort, 
        ProtocolType = NetType.Tcp 
    }; // create a use NewLife.Net Server service, only TCP protocol 
 
    server.Received the async + = (X, Y) =>  
   {
       // received document 
       var session = x as NetSession;
       (! (y.Message IS Packet PK)) IF return; 
 
       int.TryParse (Encoding.UTF8.GetString (pk.ReadBytes (0, 1)), var fileState OUT); // file status byte 1 
       int.TryParse ( Encoding.UTF8.GetString (pk.ReadBytes (1, 10) ), out var headinfo); // file total length of 10 bytes 
       int.TryParse (Encoding.UTF8.GetString (pk.ReadBytes (11, 8)), out var fileNameLength); // 8-byte file name length 
       var fileName = Encoding.UTF8.GetString (pk.ReadBytes (19 , fileNameLength)); // file name 
       int.TryParse (Encoding.UTF8.GetString (pk.ReadBytes (19 + fileNameLength, 10)), out var offset); // position offset 10 bytes 
       var data = pk.ReadBytes (29 + fileNameLength , pk.Count - (29 + fileNameLength)); // data content 
       if (data == 0 .length) return; 
  
       the await Task.Run (the async () =>
        { 
            var writeData = Data;
            the using (var = new new FileStream the FileStream ($ "} {Program.SaveDir \\ {fileName}", FileMode.OpenOrCreate, 
                FileAccess.Write, FileShare.ReadWrite)) 
            { 
                filestream.Seek (offset, SeekOrigin.Begin); 
                the await FileStream. WriteAsync (writeData, 0, writeData.Length); 
                the await filestream.FlushAsync (); 
            } // writing data to files 
        }); 
 
       XTrace.WriteLine ($ @ "status: {fileState}, ID: {session.ID}, file total length: {headinfo}, filename length: {fileNameLength}, file name: {fileName}, offset: {offset}, content-length: data.length {} "); 
       //XTrace.Log.Debug(Encoding .UTF8.GetString (pk.Data)); // output log 
   };  
    server.Add <StandardCodec> (); // stick package solution, introducing StandardCodec
    server.start ();
    Btn_Start.Text = string.Equals("启动", Btn_Start.Text) ? "停止" : "启动";
    foreach (Control control in Controls)
    {
        if (!(control is Button) && !(control is TextBox)) continue;
        if (control.Name != "Btn_Start")
        {
            control.Enabled = false;
        }
    }
}

Code that executes when triggered surveillance events

private static void OnProcess(object source, FileSystemEventArgs e)
{
    if (e.ChangeType == WatcherChangeTypes.Created)
    {
        OnCreated(source, e);
    }
    //else if (e.ChangeType == WatcherChangeTypes.Changed)
    //{
    //    OnChanged(source, e);
    //}
    //else if (e.ChangeType == WatcherChangeTypes.Deleted)
    //{
    //    OnDeleted(source, e);
    //}
 
}

When monitoring the implementation of the code to create the file

/// <the Summary> 
/// creates an event monitor file, write file after 10 seconds delay sending queue, preventing the file has not been created on the implementation of sending (copy finish within 10 seconds of the same problematic) 
/// first a 0 represents the new file represents the last resume represents 
/// 2-11 bits represent the total length of the file 
/// file name length of 12 - 18 bits represent 
19 /// - N-bit information representing the file name 
/// 19 - (N + 1) - offset position, denotes an offset position of the file transmitted 
/// 29+ (N + 1) - indicates the end of the transmitted content file 
/// < / Summary> 
/// <param name = "Source"> </ param> 
/// <param name = "E"> </ param> 
Private static void the OnCreated (Source Object, the FileSystemEventArgs E) 
{ 
    Task.Run (the async () => 
      { 
          the await Task.Delay (10000); 
          var = new new NetUri the TcpClient ($ "TCP: // {} remoteip: remotePort {}"); // needs to be sent to a remote server 
          var Netclient = TcpClient.CreateRemote ( ); 
          Netclient.Log = XTrace.Log ;
          Netclient.LogSend = true;
          Netclient.LogReceive = true;
          Netclient.Add<StandardCodec>();
          Netclient.Received += (s, ee) =>
          {
              if (!(ee.Message is Packet pk1)) return;
              XTrace.WriteLine("收到服务器:{0}", pk1.ToStr());
          };
          if (!File.Exists(e.FullPath)) return;
 
          byte[] data;
          using (var streamReader = new FileStream(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
          {
              if (streamReader.CanRead)
              {
                  data = new byte[streamReader.Length];
                  streamReader.ReadAsync the await (Data, 0, (int) streamReader.Length); 
              } 
              the else 
              { 
          var = fileNameByte new new byte [e.Name.Length]; // file name
                  XTrace.Log.Error ($ "{e.FullPath} inaccessible"); 
                  return; 
              } 
          } 
 
          var fileState Encoding.UTF8.GetBytes = ( "0"); // send a new file 
 
          var headinfo = new byte [10] ; // total length 
          headinfo = Encoding.UTF8.GetBytes (data.Length.ToString ()); 
 
          var = fileNameLength new new byte [. 8]; // file name length 
          fileNameLength = Encoding.UTF8.GetBytes (Encoding.UTF8.GetBytes (e .name) .Length.ToString ()); 
          the while (data.length> offset) 
          {
 
          = Encoding.UTF8.GetBytes fileNameByte (e.name); 
 
          var offset = 0; // offset 
          var sendLength = 409600; // single transmission size 
          Netclient.Open (); 
              IF (offset> 0) 
              { 
                  fileState = Encoding .UTF8.GetBytes ( "1"); // append file 
              } 
              IF (sendLength> data.length - offset) 
              { 
                  sendLength = data.length - offset; 
                  fileState Encoding.UTF8.GetBytes = ( "2"); // last a transmission 
              } 
              var = offsetByte new new byte [10]; // offset byte 
              offsetByte = Encoding.UTF8.GetBytes (offset.ToString ()); 
              // send a byte total
              the sendData new new byte = var [. 1. 8 + 10 + 10 + + + fileNameByte.Length sendLength]; 
              offset + = sendLength; 
              // file status 0 1 first transmits the additional file 2 last 
              Array.Copy (fileState, 0, sendData, 0, fileState.Length);
              The total length of the file // 
              Array.Copy (headinfo, 0, the sendData,. 1, headinfo.Length); 
              // file name length 
              Array.Copy (fileNameLength, 0, the sendData,. 11, fileNameLength.Length); 
              // file name information 
              Array .copy (fileNameByte, 0, the sendData,. 19, fileNameByte.Length); 
              // the content offset 
              Array.Copy (offsetByte, 0, the sendData, + fileNameByte.Length. 19, offsetByte.Length); 
              // time of transmission offsetByte content is 10 Bytes 
              Array.Copy (Data, offset, the sendData, 29 + fileNameByte.Length, sendLength); 
              var new new Packet PK = (the sendData); 
              Netclient.SendMessage (PK); 
          }
          //Netclient.Close ( "transmission completion, close the connection."); 
      }); 
}

Renderings:

Unimplemented features:

http

the reason:

1, in the course, found NewLife.Net does not support ordinary Socket programming that may have been Receive to receive follow-up operation flow (TCP protocol), each time the flow reaches will trigger an event, which had sent each time when they are bring some header information (a file name, offset, size, etc.), potentially increasing the flow rate.

2, the moment when the effect NewLife.Net received by the server, and when the order of the packet is not consistent with the client's Send (e.g., a client sends 12,345), the server 21 may be received by 354 in this order, this problem may be with me asynchronous relationship, supposedly TCP packet order is guaranteed, I have a question on GitHub, is awaiting author (big stone: https: // www. cnblogs.com/nnhy/) solution.

Guess you like

Origin www.cnblogs.com/wdw984/p/11008385.html