2012-02-17 13 views
1

私はクライアントからファイルを受け取るためにTCPサーバを設計しています。 1人のクライアントのために働いています。しかし、サーバーは複数のクライアントに応答する必要があります。私はどのように同時にクライアントから複数のファイルを受信するのか分からない。私を助けてください。C#TCPを使ったMutltiスレッドのファイル転送

サーバコード:

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操作がたくさんあることを意味するはずです。すでに並行して作業しているはずです...? –

+0

あなたの質問は何ですか?何がうまくいかない?たぶん、http://codereview.stackexchange.com/がより良い場所です。 –

+0

2つのファイルをサーバーに送信すると、 "fileName = Encoding.UTF8.GetString(state.buffer、4、fileNameLen);行で" ArgumentOutOfRangeException was unhandled " – Murugesan

答えて

0

が自然IOスレッドプールを使用し、同時に動作します。受け入れを許可し、接続ごとの状態管理(例えば、受信バッファー)を持つだけです。

また、通信のワーカーコードをUIコードから完全に分離することをお勧めします(ほとんどのサーバーはログオンを必要とせずに動作することが予想されます)。

関連する問題