Skip to content

Instantly share code, notes, and snippets.

@kenanhancer
Created October 25, 2018 00:04
Show Gist options
  • Save kenanhancer/feb0250ea4c8a895dabcefb37eb77fda to your computer and use it in GitHub Desktop.
Save kenanhancer/feb0250ea4c8a895dabcefb37eb77fda to your computer and use it in GitHub Desktop.
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp6
{
internal class Program
{
private const string host = "127.0.0.1";
private const int port = 8080;
private const string _sourcePath = @"C:\SourceDir";
private const string _destinationPath = @"C:\TestCopy";
private static int _consoleTop = 1;
private static readonly char[] _progressCharacters = @"/-\|".ToArray();
private static void Main(string[] args)
{
MainAsync().ConfigureAwait(false).GetAwaiter().GetResult();
}
private static async Task MainAsync()
{
CancellationTokenSource cts = new CancellationTokenSource();
Console.CancelKeyPress += (s, e) =>
{
e.Cancel = true;
cts.Cancel();
};
if (Directory.Exists(_destinationPath))
{
Directory.Delete(_destinationPath, true);
}
Directory.CreateDirectory(_destinationPath);
Task tcpListenerTask = StartTcpListener(host, port, cts.Token);
Task tcpClientTask = StartTcpClient(host, port, cts.Token);
await Task.WhenAll(tcpListenerTask, tcpClientTask);
}
private static async Task StartTcpListener(string ip, int port, CancellationToken token)
{
TcpListener tcpListener = new TcpListener(IPAddress.Parse(ip), port);
tcpListener.Start(2);
TcpClient acceptedTcpClient;
string fileName;
int receiveBufferSize = 8 * 1024;
int bytesRead;
long totalBytesRead = 0;
byte[] bytesBuffer;
string fileNameAndSize;
string[] fileNameAndSizeArray;
bool firstCall = true;
string message;
while (!token.IsCancellationRequested)
{
try
{
acceptedTcpClient = await tcpListener.AcceptTcpClientAsync().ContinueWith(t => t.Result, token);
using (NetworkStream networkStream = acceptedTcpClient.GetStream())
{
bytesBuffer = new byte[1024];
bytesRead = await networkStream.ReadAsync(bytesBuffer, 0, 1024, token);
fileNameAndSize = Encoding.UTF8.GetString(bytesBuffer, 0, Array.IndexOf(bytesBuffer, (byte)0));
fileNameAndSizeArray = fileNameAndSize.Split('|');
fileName = fileNameAndSizeArray[0];
message = $"Server is receiving bytes from client ({acceptedTcpClient.Client.RemoteEndPoint}) for {fileName} ";
int.TryParse(fileNameAndSizeArray[1], out int fileNameBytesCount);
int currentTop = Interlocked.Increment(ref _consoleTop);
firstCall = true;
using (FileStream fileStream = File.OpenWrite(Path.Combine(_destinationPath, fileName)))
{
totalBytesRead = 0;
bytesBuffer = new byte[receiveBufferSize];
while ((bytesRead = await networkStream.ReadAsync(bytesBuffer, 0, receiveBufferSize, token)) > 0)
{
await fileStream.WriteAsync(bytesBuffer, 0, bytesRead, token);
totalBytesRead += bytesRead;
ShowProgress(firstCall, message, totalBytesRead, fileNameBytesCount, currentTop);
firstCall = false;
}
}
}
}
catch (Exception)
{
}
}
}
private static async Task StartTcpClient(string ip, int port, CancellationToken token)
{
string[] files = Directory.GetFiles(_sourcePath);
FileInfo sourceFi;
int sendBufferSize = 8 * 1024;
int bytesRead;
long totalBytesRead = 0;
byte[] bytesBuffer;
bool firstCall = true;
string message;
long fileSize;
try
{
foreach (string sourceFilePath in files)
{
using (TcpClient tcpClient = new TcpClient())
{
await tcpClient.ConnectAsync(IPAddress.Parse(ip), port);
using (NetworkStream networkStream = tcpClient.GetStream())
{
sourceFi = new FileInfo(sourceFilePath);
message = $"Client ({tcpClient.Client.LocalEndPoint}) is sending bytes to server ({tcpClient.Client.RemoteEndPoint}) for {sourceFi.Name} ";
fileSize = sourceFi.Length;
totalBytesRead = 0;
int currentTop = Interlocked.Increment(ref _consoleTop);
bytesBuffer = new byte[1024];
Encoding.UTF8.GetBytes($"{sourceFi.Name}|{sourceFi.Length}").CopyTo(bytesBuffer, 0);
await networkStream.WriteAsync(bytesBuffer, 0, 1024, token);
firstCall = true;
using (FileStream fileStream = sourceFi.OpenRead())
{
bytesBuffer = new byte[sendBufferSize];
while ((bytesRead = await fileStream.ReadAsync(bytesBuffer, 0, sendBufferSize, token)) > 0)
{
await networkStream.WriteAsync(bytesBuffer, 0, bytesRead);
totalBytesRead += bytesRead;
ShowProgress(firstCall, message, totalBytesRead, fileSize, currentTop);
firstCall = false;
}
}
}
}
}
}
catch (Exception)
{
}
}
private static void ShowProgress(bool firstCall, string message, long processed, long total, int cursorTop)
{
long percent = (100 * (processed + 1)) / total;
long characterIndex = (percent + 1) & 3;
lock (typeof(Console))
{
int msgLenght = message.Length;
if (firstCall)
{
Console.ForegroundColor = ConsoleColor.White;
Console.SetCursorPosition(0, cursorTop);
Console.Write(message);
}
Console.SetCursorPosition(msgLenght, cursorTop);
if (percent >= 100)
{
percent = 100;
Console.ForegroundColor = ConsoleColor.Green;
Console.Write($"{percent}% [OK]");
}
else
{
Console.ForegroundColor = ConsoleColor.Red;
Console.Out.Write($"{percent}% [{_progressCharacters[characterIndex]}]");
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment