Click here to Skip to main content
11,492,385 members (64,789 online)
Click here to Skip to main content

File Transfer using WCF and Socket

, 7 Jun 2009 CPOL 91.8K 12.2K 113
Rate this:
Please Sign up or sign in to vote.
This article will show how to transfer some data from one point to another


This article will show you how to write a specific program for transferring files and folder through network using WCF (Windows Communication Foundation) and TCP clients.


  • When program runs, we start a new WCF service on the specific port with number 7634
  • Each client has his own proxy, which provides functionality for working with this service.
  • One client connects to another with this proxy and calls TransferClient.SendQuery(string ip, FilesTransfer transfer,string sport)
  • If another client accepts it begins to exchange files data through the Sockets on the random port?.


All logic of a file transfer shares on two main parts - communicating with client's WCF service and working with Sockets. So, I'll try to explain how it works in the real program.

First Step - WCF Service

If you don't know what is WCF and how it works, I strongly recommend you to read an article, Windows Communication Foundation FAQ quick starter Part 1.
All web service code is located in ITransfer.cs file. The service interface provides one method SendQuery, which is necessary for inquiry to the client.

[ServiceContract(SessionMode = SessionMode.Required)]
    public interface ITransfer
        IEnumerable<object> SendQuery(string ip, FilesTransfer transfer, int sport);

As you can see, the SessionMode attribute is set as Required. It means that for each client, a separate session will be created.
Also in this piece of code, the FilesTransfer class is involved. It is used for reception of information about files by another client. Realisation is resulted below:

    public class FilesTransfer
        public Action Action { get; set; } // The action of the packet
        public string Name { get; set; } //Client name
        public string Id { get; set; } //Identification
        public List<Transfer> Files { get; set; } //the list of the file

        public FilesTransfer()
            Files = new List<transfer />();

        public FilesTransfer(Action action)
            : this()
            Action = action;

Let's stop on the list of files. It is a simple generic enumeration of Transfer class. This class comprises information on each file or the catalogue separately. If the list contains a folder, it means that it also contains all files and directories below on the hierarchy tree. It is reached by the recursive algorithm:

    public class Transfer
        public string Name { get; set; }
        public long Length { get; set; }
        public string Catalog { get; set; }
        public string Id { get; set; }
        public string FullPath { get; set; }
private List<Transfer> RecurseFolder(string root, string folderName)
            List<Transfer> result = new List<Transfer>();
            DirectoryInfo info = new DirectoryInfo(root + folderName); //get information
						// about current directory
            foreach (FileInfo file in info.GetFiles()) // get all files from 
						// "folderName" folder
                Transfer transfer = new Transfer();
                transfer.Catalog = folderName.Substring(1); //without slash sign
                transfer.Id = Guid.NewGuid().ToString() + Guid.NewGuid().ToString();
                transfer.Length = file.Length;
                transfer.Name = file.Name;
                transfer.FullPath = file.FullName;
            foreach (DirectoryInfo dir in info.GetDirectories())
                //recursively get all files from directories
	       result.AddRange(RecurseFolder(root, folderName + @"\" + dir.Name)); 
            return result;

Well, when FilesTransfer class is full of necessary data, let's look at how the SendQuery method implements in the web service. Having received the necessary information, after the MessageBox.Show() request, the new TProgress form is created and client socket port is generated. The client is completely prepared for the data transferring to begin.

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession,
        ConcurrencyMode = ConcurrencyMode.Multiple, 
	UseSynchronizationContext = false, IncludeExceptionDetailInFaults = true)]
    public class TransferClass : ITransfer
        AutoResetEvent tcontinue = new AutoResetEvent(false);
        TProgress form;

        public IEnumerable<object> SendQuery
		(string ip, FilesTransfer transfer, int sport)
            int port = 0;
            switch (transfer.Action)
                case Action.Invite: 
                        port = HelpClass.GetAvailablePort(); 	//getting free port 
							//from the system
                        if (MessageBox.Show(string.Format("Accept {0} files from {1}", 
			transfer.Files.Count, transfer.Name), "Files", 
			MessageBoxButtons.YesNo) == DialogResult.Yes)
                            ThreadStart start = delegate
                                form = new TProgress(null, port);
                       = sport;
                                form.GetThread = new Thread
				(new ParameterizedThreadStart(form.GetInvoke));
                            HelpClass.Form.BeginInvoke(start); //if we call thread 
					// by "this.Invoke()" the parental stream 
					// would be lost and we couldn't turn to 
					// other elements of a "form" class
                        else return new List<object>() { (int)InviteRusult.Cancel, 0 };
                        return new List<object>() { (int)InviteRusult.Busy, 0 };
            return new List<object>() { (int)InviteRusult.Ok, port };

Second Step - Socket Transferring

Now when both ports for a socket are known, clients connect to each other and begin to transfer byte data. But it isn't a model like "client-server" because when one file is passed the socket which was a server for the one moment becomes a client and also a client becomes a server. It is necessary because the server does not know when the client has completely accepted the handed over information and that there are no overloads or information leakage. It stops the action till the moment when the client will inform that all is accepted. If the type is directory, client simply creates it in the necessary folder. Let's look at the server side sender:

public void SendInvoke(object obj)
                FilesTransfer ft = (FilesTransfer)(obj as List<object>)[0]; //get file 
					//information which you want to transfer
                ThreadStart ts = delegate //invocation of the main thread
                    progressBar1.Maximum = (int)(ft.Files.Sum(t => t.Length) / 4);
                progressBar1.Invoke(ts, null);
                IPEndPoint sendTo = (IPEndPoint)(EndPoint)(obj as List<object>)[1];//get
				// the address of the client we want to connect
                TcpClient client = new TcpClient(new IPEndPoint(IPAddress.Any, sport));
                client.BeginConnect(sendTo.Address, sendTo.Port, 
		new AsyncCallback(Connected), null); //opening connection
                connected.WaitOne(); //sleep till the client answered
                long sended = 0;
                foreach (TransferNamespace.Transfer t in ft.Files)
                    using (FileStream stream = new FileStream
			(t.FullPath, FileMode.Open, FileAccess.Read, FileShare.Read))
                        ts = delegate
                            progressBar2.Value = 0;
                            progressBar2.Maximum = (int)t.Length;
                            textBox1.Text = t.Name;
                        this.Invoke(ts, null);
                        client.SendBufferSize = 65 * (int)Math.Exp
				(6 * System.Math.Log(10)); //like 65 10^6
                        sended = 0;
                        stream.Seek(0, SeekOrigin.Begin); //seek the pointer 
						   //to the begin of the file
                        while (true)
                            byte[] bytes; //we will send the data by 20000 sized packets
                            if (sended >= stream.Length) break;
                            if (stream.Length - sended < 20000)
                                bytes = new byte[stream.Length - sended]; //if it is 
							//the last packet
                                bytes = new byte[20000];
                            sended += bytes.Length; //increment the counter of 
						// the sended data
                            ThreadStart asdasd = delegate
                                progressBar1.Value += (int)bytes.Length / 4;
                                progressBar2.Value += (int)bytes.Length;
                            this.Invoke(asdasd, null);
                            stream.Read(bytes, 0, bytes.Length);
                            client.Client.Send(bytes, SocketFlags.Partial); //sending 
							//by "streaming" mode
                    client.Client.Receive(new byte[1]); //sleep for accepting 
					//that client completely got the file
                ts = delegate
                    textBox1.Text = "Sended.";
                this.Invoke(ts, null);
            catch { MessageBox.Show("Aborted"); }

And client:

public void GetInvoke(object obj)
                string path = Application.StartupPath + @"\Files\"; //get the full 
						//path to the file location
                byte[] overthrow = new byte[0]; //for the surplus data
                FilesTransfer tr = (FilesTransfer)obj;
                ThreadStart callback = delegate
                    progressBar1.Maximum = (int)tr.Files.Sum(t => t.Length) / 4;
                progressBar1.Invoke(callback, null);
                TcpListener listener = new TcpListener(port);
                TcpClient client = listener.AcceptTcpClient();
                callback = delegate
                    this.Text = string.Format("Getting from {0}", 
		   (client.Client.RemoteEndPoint as IPEndPoint).Address.ToString());
                this.Invoke(callback, null);
                client.ReceiveBufferSize = 65 * (int)Math.Exp(6 * System.Math.Log(10));
                foreach (TransferNamespace.Transfer t in tr.Files)
                    if (t.Catalog != "<root>" && !Directory.Exists(path + t.Catalog))
                        Directory.CreateDirectory(path + t.Catalog);
                    FileStream stream = new FileStream(path + 
			(t.Catalog == "<root>" ? "" : t.Catalog) + 
			t.Name, FileMode.OpenOrCreate, FileAccess.Write);
                    ThreadStart todo = delegate
                        progressBar2.Value = 0;
                        progressBar2.Maximum = (int)t.Length;
                        textBox1.Text = t.Name;
                    this.Invoke(todo, null);
                    long getted = 0;
                    if (overthrow.Length > 0) //If there are surpluses of the data, 
			//we are going to put it in the beginning of the new file
                        int gotted = 0;
                        if (overthrow.Length <= t.Length)
                            stream.Write(overthrow, 0, overthrow.Length);
                            gotted = overthrow.Length; //increment and start for 
						//normally getting other data
                        else //it means that we got the data of two files. 
				//It can be if files are very small
                            byte[] otherbuf = overthrow.Without(0, t.Length);
                            stream.Write(otherbuf, 0, otherbuf.Length);
                            overthrow = overthrow.Without(t.Length);
                            gotted = otherbuf.Length;
                        stream.Flush(); //writing in the file
                        getted = gotted;
                        todo = delegate
                                progressBar1.Value += (int)gotted / 4;
                                progressBar2.Value += (int)gotted;
                            catch { }
                        this.Invoke(todo, null);
                    while (getted < t.Length)
                        byte[] buffer = new byte[client.Client.Available]; //get new 
                        client.Client.Receive(buffer, SocketFlags.Partial);
                        getted += buffer.Length; //increment the counter
                        if (getted > t.Length) //if we got more data that needs 
			//for current file, it must be located in the specified array
                            long length = (long)getted - t.Length;
                            overthrow = buffer.Without(buffer.Length - length);
                            buffer = buffer.Without(0, buffer.Length - length);
                            getted -= length;
                        todo = delegate
                                progressBar1.Value += (int)buffer.Length / 4;
                                progressBar2.Value += (int)buffer.Length;
                            catch { }
                        this.Invoke(todo, null);
                        stream.Write(buffer, 0, buffer.Length);
                    client.Client.SendTo(new byte[1] { 1 }, 
			new IPEndPoint((client.Client.RemoteEndPoint 
			as IPEndPoint).Address, sport)); //continue sending data
                callback = delegate
                    textBox1.Text = "Getted.";
                this.Invoke(callback, null);
            catch { MessageBox.Show("Aborted"); }


All in all, pluses in this architecture are that we could keep many connections and transferring processes. Using such technologies as WCF, we don't care about serialization of objects and working with channels. There are ways of transferring a stream through web service, but it is not our choice. Socket provides us with a high speed, not only client-server architecture and more comfortable interface.


  • 7th June, 2009: Initial post


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Artem S. Dmitriev
Software Developer
Russian Federation Russian Federation
No Biography provided

Comments and Discussions

Questionqurey about sending file to another remote computer on network Pin
Member 1031223127-Nov-13 19:53
memberMember 1031223127-Nov-13 19:53 
AnswerRe: qurey about sending file to another remote computer on network Pin
fanorng19852-Dec-13 17:13
memberfanorng19852-Dec-13 17:13 
SuggestionGood Article Pin
garlapally15-Sep-12 22:49
membergarlapally15-Sep-12 22:49 
Question[My vote of 2] how to run the demo Pin
imak12-May-12 9:19
memberimak12-May-12 9:19 
QuestionFolder Transfer Pin
Navin Kumar K Subramanian1-May-12 21:47
groupNavin Kumar K Subramanian1-May-12 21:47 
Hi asprodotru,

is there is a way to transfer a folder by using this service please let me know. and more over where is the server side code?. can yo please help me with that.


hai i cant include ("cryptopp551.dll") this dll in my C# project please say solution or send me any DLL file that is capable of encrypt a password by use of a key
GeneralMy vote of 5 Pin
delibey9-Feb-12 14:00
memberdelibey9-Feb-12 14:00 
QuestionFile transfer Pin
mohanrajkiller11-Nov-11 1:03
membermohanrajkiller11-Nov-11 1:03 
GeneralThanks Pin
zevassyrossa6-May-11 23:15
memberzevassyrossa6-May-11 23:15 
QuestionCan you give us the source code of the web service? Pin
kaphwankim29-Nov-10 13:24
memberkaphwankim29-Nov-10 13:24 
GeneralMy vote of 4 Pin
Summer Xia17-Jul-10 5:51
memberSummer Xia17-Jul-10 5:51 
GeneralPlease help with service connecting Pin
ChauNTran12-Jul-10 14:09
memberChauNTran12-Jul-10 14:09 
GeneralSubdirectory creation with: "&lt root &gt" Pin
ElBuitre7-Apr-10 23:21
memberElBuitre7-Apr-10 23:21 
GeneralRe: Subdirectory creation with: "&lt root &gt" Pin
martyn_mcfly8-Apr-10 2:25
membermartyn_mcfly8-Apr-10 2:25 
GeneralRe: Subdirectory creation with: "&lt root &gt" Pin
ElBuitre8-Apr-10 3:51
memberElBuitre8-Apr-10 3:51 
GeneralRe: Subdirectory creation with: "&lt root &gt" Pin
martyn_mcfly10-Apr-10 22:04
membermartyn_mcfly10-Apr-10 22:04 
GeneralPeer-to-peer twist Pin
bleekay6-Apr-10 19:06
memberbleekay6-Apr-10 19:06 
GeneralAlternative recursive scan Pin
Anton Levshunov25-Nov-09 5:43
memberAnton Levshunov25-Nov-09 5:43 
GeneralExplanation of when and how the service reference was created Pin
bubk12-Nov-09 5:50
memberbubk12-Nov-09 5:50 
QuestionUsing BasicHttpBinding Pin
Odedk1-Nov-09 5:47
memberOdedk1-Nov-09 5:47 
GeneralIt doesn't work... Pin
mancardo11-Sep-09 16:27
membermancardo11-Sep-09 16:27 
GeneralRe: It doesn't work... Pin
Lucio Flavio25-Feb-10 7:34
memberLucio Flavio25-Feb-10 7:34 
GeneralNeed more explaination Pin
MoePOo2-Sep-09 16:01
memberMoePOo2-Sep-09 16:01 
JokeThanks Pin
hamed3242124-Jun-09 20:15
memberhamed3242124-Jun-09 20:15 
GeneralRe: Thanks Pin
martyn_mcfly24-Jun-09 23:16
membermartyn_mcfly24-Jun-09 23:16 
GeneralNice Article, thanks Pin
Jon-Hawkins8-Jun-09 1:16
memberJon-Hawkins8-Jun-09 1:16 
AnswerRe: Nice Article, thanks Pin
martyn_mcfly8-Jun-09 2:15
membermartyn_mcfly8-Jun-09 2:15 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.150520.1 | Last Updated 7 Jun 2009
Article Copyright 2009 by Artem S. Dmitriev
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid