Sunday, November 15, 2009

CLIENT / SERVER : Simple File Sharing and File Transfer

This article will demostrate a simple file sharing technique between 2 computers using sockets. A client can search and download a file shared by the server and a server can search and download a file shared by the client




SERVER
Two computers can transfer file with each other over a socket connection. A server computer opens a socket connection and listens on a pre-defined port for imcoming client connection. Once a connection is establised a client and server can handshake using simple commands to search files and initiate a transfer.
To being using sockets in the application , use System.Net namespace

using System.Net;
using System.Net.Sockets;

Create the server socket of the type Stream and using the TCP protocol.
    serversocket = new Socket(AddressFamily.InterNetwork,
              SocketType.Stream, ProtocolType.Tcp);
    serversocket.Blocking = true ;

Bind the Server to the port and keep listening on the port for client connections ..
    IPHostEntry IPHost = Dns.Resolve(server); 
    string []aliases = IPHost.Aliases; 
    IPAddress[] addr = IPHost.AddressList; 
    IP_ADDRESS.Text = addr[0].ToString();
    IPEndPoint ipepServer = new IPEndPoint(addr[0], 8090);
    serversocket.Bind(ipepServer);
    serversocket.Listen(-1);

Once a client is connected create a thread to talk to the client.
  while ( true ) 
  {
    clientsock = serversocket.Accept();
    if ( clientsock.Connected ) 
    {
      total_clients_connected++;
      AppendText("Client connected...") ;
      Thread tc = new Thread(new ThreadStart(listenclient));
      tc.Start();
    }
  }

The client and server exchanges commands until the client disconnects ..
void listenclient()
{
  Socket sock = clientsock ;
  string cmd = server ;
  byte[] sender = System.Text.Encoding.ASCII.GetBytes("SERVER " + cmd) ;
  sock.Send(sender, sender.Length,0) ;

  try
  {
    while ( sock != null ) 
    {
      cmd = "" ;
      byte[] recs = new byte[32767];
      int rcount = sock.Receive(recs,recs.Length,0) ;
      string clientmessage = System.Text.Encoding.ASCII.GetString(recs) ;
      clientmessage = clientmessage.Substring(0,rcount);
      
      string smk = clientmessage ;

      cmdList = null ;
      cmdList = clientmessage.Split(' ');
      string execmd = cmdList[0];
      AppendText("COMMAND==>" + execmd) ;

      sender = null ;
      sender = new Byte[32767];

      Console.WriteLine("CLIENT COMMAND = " + execmd + "\r\n");

      string parm1 = "";
      if ( execmd == "USER" ) 
      {

        login_client_machine = cmdList[2];
        string pass = cmdList[3];
        string ip = cmdList[1];
        AppendText("Client Connected IP:" + ip + " User :" + login_client_machine );
        continue ;
      }

      if ( execmd == "GET" ) 
      {
        // GET  
        for ( int i=1 ; i < cmdList.Length-1;i++)
          parm1 = parm1 + " " + cmdList[i];
        parm1 = parm1.Trim();
        FileInfo fi = new FileInfo(parm1);          
        if ( fi.Exists ) 
          cmd = "GETOK " ;
        else
          cmd = "GETOK_FAILED " ;
        sender = System.Text.Encoding.ASCII.GetBytes(cmd) ;
        sock.Send(sender, sender.Length,0) ;
        continue;
      }

      if ( execmd == "LISTING" ) 
      {
        PopulateList(clientmessage);
        continue ;
      }

      if ( execmd == "SERVER_LISTING" ) 
      {
        sender = new Byte[32767];
        cmd="LISTING \r\n";
        parm1 = cmdList[1];
        
        cmd = cmd + SearchDatabase(parm1);

        sender = System.Text.Encoding.ASCII.GetBytes(cmd) ;
        sock.Send(sender, sender.Length,0) ;
        continue ;
      }

      if ( execmd == "NOOP" )
      {
        // do nothing 
        continue ;
      }

      if ( execmd == "CLIENT_DISCONNECTING" ) 
      {
        cmd = "CLIENT_CLOSE";
        sender = System.Text.Encoding.ASCII.GetBytes(cmd) ;
        sock.Send(sender, sender.Length,0) ;

        sock.Close();
        AppendText("Client Disconnected");
        continue ;
      }


      if ( execmd == "FILEOK" ) 
      {
        cmd = "NOOP ";
        sender = System.Text.Encoding.ASCII.GetBytes(cmd) ;
        sock.Send(sender, sender.Length,0) ;
        continue ;
      }
      
      if ( execmd == "GETOK" )
      {
        cmd = "BEGINSEND "  + shared_file_path + " " + shared_file_size ;
        sender = new Byte[1024];
        sender = Encoding.ASCII.GetBytes(cmd);
        sock.Send(sender, sender.Length , 0 );
        ServerDownloadingFromClient(sock);
        continue ;
      }

      if ( execmd == "BEGINSEND" ) 
      {
        ClientDownloadingFromServer(cmdList , sock);
        continue ;
      }
    }
  }
  catch(Exception Se)
  {
    string s = Se.Message;
    Console.WriteLine(s);
  }
}


 
FILE TRANSFER
To begin a file transfer operation the Server and client opens a NetworkStream object using the current connected socket. NetworkStream implements the standard .NET Framework stream mechanism to send and receive data through network sockets. NetworkStream supports both synchronous and asynchronous access to the network data stream.
Once the server creates the stream, it opens the selected file, begins reading the file and outputs the data to the stream.

  while(rdby < total && nfs.CanWrite)
  {
    //Read from the File (len contains the number of bytes read)
    len =fin.Read(buffed,0,buffed.Length) ;
    //Write the Bytes on the Socket
    nfs.Write(buffed, 0,len);
    //Increase the bytes Read counter
    rdby=rdby+len ;
          
    int pc = (int)( ((double)rdby/(double)total ) * 100.00) ;
    string perc = pc.ToString() + "%" ;
    listView4.Items[cnt].SubItems[3].Text = perc;
    listView4.Items[cnt].SubItems[2].Text = rdby.ToString();
  }

The client in turn will read from the same network stream opened for the underlying socket, read the bytes sent by the server and writet to the output file.
NetworkStream nfs = new NetworkStream(sock) ;

try
{
        //loop till the Full bytes have been read
        while(rby < size)
        {
        byte[] buffer = new byte[1024] ;
        //Read from the Network Stream
      int i = nfs.Read(buffer,0,buffer.Length) ;
      fout.Write(buffer,0,(int)i) ;
      rby=rby+i ;

      int pc = (int)( ((double)rby/(double)size ) * 100.00) ;
      string perc = pc.ToString() + "%";
      listView3.Items[cnt].SubItems[3].Text = perc;
      listView3.Items[cnt].SubItems[2].Text = rby.ToString();

    }  
  fout.Close() ;
  string cmd = "FILEOK" ;
  Byte[] sender = new Byte[1024];
  sender = new Byte[1024];
  sender = Encoding.ASCII.GetBytes(cmd);
  sock.Send(sender , sender.Length , 0 );
}


Once the file is downloaded , the client informs the server that the file transfer was successful by sending the FILE_OK command.
CLIENT
The client connects to the server at the pre-defined port ( 8090 ) .
  try
  {
    serversocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    serversocket.Blocking = true ;
    IPHostEntry IPHost = Dns.Resolve(textBox1.Text);
    string []aliases = IPHost.Aliases; 
    IPAddress[] addr = IPHost.AddressList; 
    IPEndPoint ipepServer = new IPEndPoint(addr[0], 8090);
    serversocket.Connect(ipepServer);
    clientsock = serversocket; 
  } 

Once the connection to the server is established, the client begins a thread to talk to the server.


See full details: http://www.csharphelp.com/archives2/archive335.html

No comments: