2012-02-17 46 views
1

我正在設計用於從客戶端接收文件的TCP服務器。它爲一個客戶端工作。但服務器需要響應多個客戶端。我不知道如何同時從客戶端接收多個文件。請幫幫我。C#多線程文件傳輸使用TCP

服務器代碼:

public partial class Form1 : Form 
{ 
    Thread t1; 
    int flag = 0; 
    string receivedPath = "yok"; 
    public delegate void MyDelegate(); 
    private string fileName; 
    public Form1() 
    { 
     t1 = new Thread(new ThreadStart(StartListening)); 
     t1.Start(); 
     InitializeComponent(); 
    } 


    public class StateObject 
    { 
     // Client socket. 
     public Socket workSocket = null; 

     public const int BufferSize = 8096; 
     // Receive buffer. 
     public byte[] buffer = new byte[BufferSize]; 
    } 

    public static ManualResetEvent allDone = new ManualResetEvent(true); 

    public void StartListening() 
    { 
     byte[] bytes = new Byte[8096]; 
     IPEndPoint ipEnd = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9050); 
     Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
     try 
     { 
      listener.Bind(ipEnd); 
      listener.Listen(100); 
      SetText("Listening For Connection"); 
      while (true) 
      { 
       allDone.Reset(); 
       listener.BeginAccept(new AsyncCallback(AcceptCallback), listener); 
       allDone.WaitOne(); 

      } 
     } 
     catch (Exception ex) 
     { 
     } 

    } 

    public void AcceptCallback(IAsyncResult ar) 
    { 
     allDone.Set(); 

     Socket listener = (Socket)ar.AsyncState; 
     Socket handler = listener.EndAccept(ar); 

     StateObject state = new StateObject(); 
     state.workSocket = handler; 
     handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); 
     flag = 0; 

    } 

    public void ReadCallback(IAsyncResult ar) 
    { 
     int fileNameLen = 1; 
     String content = String.Empty; 
     StateObject state = (StateObject)ar.AsyncState; 
     Socket handler = state.workSocket; 
     int bytesRead = handler.EndReceive(ar); 
     if (bytesRead > 0) 
     { 
      if (flag == 0) 
      { 
       fileNameLen = BitConverter.ToInt32(state.buffer, 0); 
       fileName = Encoding.UTF8.GetString(state.buffer, 4, fileNameLen); 
       receivedPath = @"D:\" + fileName; 
       flag++; 
      } 

      if (flag >= 1) 
      { 
       BinaryWriter writer = new BinaryWriter(File.Open(receivedPath, FileMode.Append)); 
       if (flag == 1) 
       { 
        writer.Write(state.buffer, 4 + fileNameLen, bytesRead - (4 + fileNameLen)); 
        flag++; 
       } 
       else 
       writer.Write(state.buffer, 0, bytesRead); 
       writer.Close(); 
       handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); 
      } 
     } 
     else 
     { 
      Invoke(new MyDelegate(LabelWriter)); 
     } 

    } 
    public void LabelWriter() 
    { 
     label1.Text = "Data has been received " + fileName; 
    } 

    private void Form1_FormClosed(object sender, FormClosedEventArgs e) 
    { 
     t1.Abort(); 
    } 


} 

客戶端代碼:

public partial class Form1 : Form 
    { 
     string splitter = "'\\'"; 
     string fName; 
     string[] split = null; 
     byte[] clientData; 

     public Form1() 
     { 
      InitializeComponent(); 
      button2.Visible = false; 
     } 

     private void button1_Click_1(object sender, EventArgs e) 
     { 
      char[] delimiter = splitter.ToCharArray(); 
      //openFileDialog1.ShowDialog(); 
      if (openFileDialog1.ShowDialog() == DialogResult.OK) 
      { 
       textBox1.Text = openFileDialog1.FileName; 
       textBox2.AppendText("Selected file " + textBox1.Text); 
       button2.Visible = true; 
      } 
      else 
      { 
       textBox2.AppendText("Please Select any one file to send"); 
       button2.Visible = false; 
      } 

      split = textBox1.Text.Split(delimiter); 
      int limit = split.Length; 
      fName = split[limit - 1].ToString(); 
      if (textBox1.Text != null) 
       button1.Enabled = true; 
     } 

     private void button2_Click_1(object sender, EventArgs e) 
     { 
      Socket clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
      //IPAddress ip = new IPAddress; 


      byte[] fileName = Encoding.UTF8.GetBytes(fName); //file name 
      byte[] fileData = File.ReadAllBytes(textBox1.Text); //file 
      byte[] fileNameLen = BitConverter.GetBytes(fileName.Length); //lenght of file name 
      clientData = new byte[4 + fileName.Length + fileData.Length]; 

      fileNameLen.CopyTo(clientData, 0); 
      fileName.CopyTo(clientData, 4); 
      fileData.CopyTo(clientData, 4 + fileName.Length); 

      textBox2.AppendText("Preparing File To Send"); 
      clientSock.Connect("127.0.0.1", 9050); //target machine's ip address and the port number 
      clientSock.Send(clientData); 
      //clientSock. 
      clientSock.Close(); 

     } 


    } 
} 
+0

這應該已經適用於多個客戶:您接受連接,開始閱讀,並開始接受(罰款);你的閱讀回調過程,然後(如有必要)開始閱讀。這應該意味着您有很多正在進行的BeginRead操作。它應該已經在並行工作......? – 2012-02-17 10:37:17

+0

你的問題是什麼?什麼不行?也許http://codereview.stackexchange.com/是一個更好的地方問。 – 2012-02-17 10:37:49

+0

如果向服務器發送兩個文件意味着在「fileName = Encoding.UTF8.GetString(state.buffer,4,fileNameLen);」行中出現此錯誤「ArgumentOutOfRangeException was unhandled」 – Murugesan 2012-02-17 10:49:38

回答

0

使用異步操作,自然會使用IO線程池,同時運行。只需允許接受並具有每個連接狀態管理(例如接收緩衝區)。

我也建議完全分離任何UI代碼的通信工作者代碼(大多數服務器預計不需要登錄就可以運行)。