Here we will see how to do multiple client server file transfer using Socket Programming. You can see a lot of documents for a simple file transfer. But this is different. Here, if the file size is large, say larger than 1 MB, I am splitting the file for sizes of 1MB and then transferring each file to the server. At the server side, the split files will be stored until all the files are received and once it is received, I am merging all the files to create the single file.
Right now this code can handle upto 14MB of files with a split size of 1MB. You can increase the split size and proportionally the file to be sent size.
Server Side code:
Please do remember to add the timer and the background worker in your form.
using System;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
// File transfer protocol Server function by Vinay
namespace Server
{
public partial class Server : Form
{
public Server()
{
InitializeComponent();
FTServer.receivedPath = "";
}
// Called when the Server start button is clicked
private void btnStart_Click(object sender, EventArgs e)
{
//Checks if the destination path is set
if (FTServer.receivedPath.Length > 0)
backgroundWorker1.RunWorkerAsync();
else
MessageBox.Show("Please select file receiving path");
}
private void timer1_Tick(object sender, EventArgs e)
{
label5.Text = FTServer.receivedPath;
label3.Text = FTServer.curMsg;
}
FTServer obj = new FTServer();
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
obj.StartServer();
}
// Sets the destination path
private void btnReceive_Click(object sender, EventArgs e)
{
FolderBrowserDialog fd = new FolderBrowserDialog();
if (fd.ShowDialog() == DialogResult.OK)
{
FTServer.receivedPath = fd.SelectedPath;
}
}
// Server is stopped and all the temporary files are deleted
private void btnStop_Click(object sender, EventArgs e)
{
FTServer.sock.Close();
FTServer.curMsg = "Server Stopped";
FTServer.deleteFiles();
}
}
//FILE TRANSFER USING C#.NET SOCKET - SERVER
class FTServer
{
IPEndPoint ipEnd;
public static Socket sock;
public FTServer()
{
//To accept any IP address with port number 5656
ipEnd = new IPEndPoint(IPAddress.Any, 5656);
// Creating a new socket with TCP protocol
sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//Bind the socket with the Ip
sock.Bind(ipEnd);
}
public static string receivedPath;
public static string curMsg = "Stopped";
// Method to receive the data sent from the client.
public void StartServer()
{
try
{
curMsg = "Starting...";
//The socket is waiting for client connection. The socket can handle maximum
// of 100 client connections at a time.
sock.Listen(100);
curMsg = "Running and waiting to receive file.";
//When a request comes from the client the socket is ready to accept
Socket clientSock = sock.Accept();
//5Mb of buffer space is allocated for the data transfer
byte[] clientData = new byte[1024 * 5000];
//The receive method returns the size of the data that is transferred.
//The size will be in bytes.
int receivedBytesLen = clientSock.Receive(clientData);
int fileNameLen = BitConverter.ToInt32(clientData, 0);
string fileName = Encoding.ASCII.GetString(clientData, 4, fileNameLen);
//If the file exists in the path, the existing file is deleted
if (File.Exists(receivedPath + "\\" + fileName))
{
File.Delete(receivedPath + "\\" + fileName);
}
curMsg = "Receiving data..." + fileName;
//Binary stream writer to save the data received from the client.
BinaryWriter bWrite = new BinaryWriter(File.Open(receivedPath + "/" + fileName, FileMode.Append));
bWrite.Write(clientData, 4 + fileNameLen, receivedBytesLen - 4 - fileNameLen);
Thread.Sleep(1000);
curMsg = "Saving file...";
//Closing the binary writer
bWrite.Close();
//Closing the socket connection
clientSock.Close();
//Calling the merger method to combine the split files into a single readable file.
mergeFiles(fileName);
StartServer();
}
catch (Exception ex)
{
curMsg = "File Receving error.";
}
}
// Merge method to combine the split files into a single readable file.
public void mergeFiles(string recvdfileName)
{
//Get all the files with the extension .vin
string[] filePaths = Directory.GetFiles(receivedPath, "*.vin");
string fileName = " ";
int parts = filePaths.Length;
for (int i = 0; i < parts; i++)
{
fileName = getFilename(0, filePaths[i]);
if (filePaths[i].IndexOf(recvdfileName) > -1)
{
//Deleting the file if the file is already present
if (File.Exists(receivedPath + "\\" + fileName))
{
File.Delete(receivedPath+ "\\" + fileName);
}
//Creating a new file with the filename
FileStream createFile = File.Create(receivedPath + "\\" + fileName);
createFile.Close();
}
}
string path = receivedPath + "\\" + fileName;
FileStream outFile = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write);
if (outFile != null)
{
outFile.Flush();
}
for (int i = 0; i < parts; i++)
{
if (filePaths[i].IndexOf(fileName) > -1)
{
FileInfo f = new FileInfo(filePaths[i]);
int size = (int)f.Length;
int data = 0;
byte[] buffer = new byte[1024 * 50000];
FileStream inFile = new FileStream(filePaths[i], FileMode.OpenOrCreate, FileAccess.Read);
//reading the data from the split file and putting it into a single file.
while ((data = inFile.Read(buffer, 0, size)) > 0)
{
outFile.Write(buffer, 0, data);
}
inFile.Close();
}
}
outFile.Close();
}
// Method to get the filenames with the extension
public string getFilename(int i, string fileName)
{
string[] array = fileName.Split('\\');
int size = array.Length;
string[] tempname = array[size - 1].Split('.');
return tempname[i] + "." + tempname[i+1];
}
// Method to delete all the files when the server stop button is clicked.
public static void deleteFiles()
{
string[] filePaths = Directory.GetFiles(receivedPath, "*.vin");
int parts = filePaths.Length;
for (int i = 0; i < parts; i++)
{
File.Delete(filePaths[i]);
}
}
}
}
Client Side:
using System;
using System.Data;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
// File transfer protocol Client function by Vinay
namespace Client
{
public partial class Client : Form
{
public Client()
{
InitializeComponent();
}
// Called when the button is clicked.
private void btnSend_Click(object sender, EventArgs e)
{
string filePath = "";
FTClientCode.curMsg = "Idle";
//Loads the windows explorer to select a file.
FileDialog loadFile = new OpenFileDialog();
if (loadFile.ShowDialog() == DialogResult.OK)
{
FileInfo file = new FileInfo(loadFile.FileName);
long fileLength = file.Length; //the length of file
//extract the name of the File to be FTPed
string fileName = getFilename(1, loadFile.FileName);
//size of File in MBs
double fileinMB = converToMB(fileLength);
string changedFileName = "";
int parts = 1;
//Checks if the sie of the file chosen in greater than 1MB
//If yes then splits the file with name with an extension .vin
if (fileinMB > 1)
{
parts = splitFile(file, fileinMB, fileName);
}
for (int i = 0; i < parts; i++)
{
if (parts == 1)
{
changedFileName = loadFile.FileName;
}
else
{
changedFileName = "C:\\Test\\" + fileName + "." + i + ".vin";
}
changedFileName = changedFileName.Replace("\\", "/");
while (changedFileName.IndexOf("/") > -1)
{
filePath += changedFileName.Substring(0, changedFileName.IndexOf("/") + 1);
changedFileName = changedFileName.Substring(changedFileName.IndexOf("/") + 1);
}
byte[] fileNameByte = Encoding.ASCII.GetBytes(changedFileName);
//Reads all the data in the file
byte[] fileData = File.ReadAllBytes(filePath + changedFileName);
byte[] clientData = new byte[4 + fileNameByte.Length + fileData.Length];
byte[] fileNameLen = BitConverter.GetBytes(fileNameByte.Length);
fileNameLen.CopyTo(clientData, 0);
fileNameByte.CopyTo(clientData, 4);
fileData.CopyTo(clientData, 4 + fileNameByte.Length);
FTClientCode.SendFile(clientData, changedFileName);
filePath = " ";
}
}
//deletes the split files after they have been trasnferred throuhg FTP
deleteFiles(loadFile.FileName);
}
// spilts the big file into smaller files of size 1MB or lesser
public static int splitFile(FileInfo f, double fileSize, string fileName)
{
int parts = (int)Math.Ceiling(fileSize / 1);
int eachSize = (int)Math.Ceiling((double)fileSize / parts) * 1024 * 1024;
FileStream inFile = new FileStream(f.ToString(), FileMode.OpenOrCreate, FileAccess.Read);
for (int i = 0; i < parts; i++)
{
string path = "C:\\Test\\" + fileName + "." + i + ".vin";
if (File.Exists(path))
File.Delete(path);
FileStream outFile = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write);
int data = 0;
byte[] buffer = new byte[eachSize];
if ((data = inFile.Read(buffer, 0, eachSize)) > 0)
{
outFile.Write(buffer, 0, data);
}
outFile.Close();
}
inFile.Close();
return parts;
}
// converts file length into Megabytes
public static double converToMB(long fileLength)
{
return (fileLength / 1024f) / 1024f;
}
public static string getFilename(int i, string fileName)
{
string[] array = fileName.Split('\\');
int length = array.Length;
return array[length - 1];
}
public void deleteFiles(string recvdfileName)
{
string[] filePaths = Directory.GetFiles("C:\\Vinay\\", "*.vin");
string fileName = " ";
int parts = filePaths.Length;
for (int i = 0; i < parts; i++)
{
fileName = getFilename(0, recvdfileName);
if (filePaths[i].IndexOf(fileName) > -1)
{
File.Delete(filePaths[i]);
}
}
}
private void timer1_Tick(object sender, EventArgs e)
{
label3.Text = FTClientCode.curMsg;
}
}
//FILE TRANSFER USING C#.NET SOCKET - CLIENT
class FTClientCode
{
public static string curMsg = "";
public static void SendFile( byte[] clientData, string fileName)
{
try
{
//create a new client socket
Socket clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// get the ipaddress
IPAddress[] ipAddress = Dns.GetHostAddresses("localhost");
// Make IP end point same as Server.
IPEndPoint ipEnd = new IPEndPoint(ipAddress[1], 5656);
curMsg = "Connection to server ...";
clientSock.Connect(ipEnd);
curMsg = "Buffering ...";
curMsg = "File sending..." + fileName;
//add some delay to let the process finish
Thread.Sleep(3000);
//send the data
clientSock.Send(clientData);
//close the client
clientSock.Close();
curMsg = "Disconnecting...";
curMsg = "Files are transferred.";
}
catch (Exception ex)
{
if (ex.Message == "No connection could be made because the target machine actively refused it")
curMsg = "File Sending fail. Because server not running.";
else
curMsg = "File Sending fail." + ex.Message;
}
}
}
}