2009-12-21 8 views
0

TcpClient 개체를 사용하여 파일을 전송하고 있습니다. 개체는 하나뿐입니다. 그래서 파일을 전송하는 동안이 객체를 잠그고 파일을 전송하여 다른 스레드가 TCPClient가 해제 될 때까지 기다렸습니다.C에서 병렬로 스레드 만들기 #

스레드가 단일 개체와 병렬로 작동하게하는 방법이 있습니까?

답변

3

아니요, 각 스레드가 자체 연결을 사용하도록 설정하십시오. 좀

+0

tcpclient.connect (REMOTEHOST, 포트) (이 닷넷 프레임 워크에서 백그라운드에서 이루어집니다) 어떤 스레드를 사용하지 않습니다 연결하면 같은 포트로 만들면서 오류 (연결을 거부 함)가 발생하고 동일한 객체가됩니다. – marshalprince

+0

그러나 하나의 연결을 사용하는 경우 서버는 함께 속한 데이터를 어떻게 알 수 있습니까? –

+0

내가하고있는 일은 연결을 만들기 위해 하나의 TCPClient를 사용하고 있으며 다른 TCPClient를 생성하고있는 파일을받는 중입니다.하지만 이제는 연결에 사용 된 첫 번째 노드를 잠글 필요가 있습니다. 하지만 중간에 다른 스레드 (데이터 용으로 새로운 TCPClient를 작성)로 데이터를 보내야하지만 연결 용으로 TCPClient가 이미 잠겨 있습니다. 그럼 어떻게 다른 파일을 보낼 수 있습니까 – marshalprince

0

....

당신이 paeallel에서 사용하는 것처럼 느낄 것이다 NetworkStream.BeginWrite을 사용할 수 있습니다 ....

0

그러면 BeginWrite/BeginRead와 현재의 스레드를 해제에 물건을 할 것입니다 배경. BeginWrite로 여러 개의 쓰기를 대기열에 넣을 수 있습니다 (그리고 병렬 작업을 이해할 수 있습니다). 내부 소켓 버퍼가 파일을 보낼 때 가득 채울 수 있기 때문에 나는 그것을 권하고 싶지 않다.

언제든지 Socket으로 전환하고 SendFile 메서드를 사용할 수 있습니다.

여러 개의 TcpClient 또는 소켓이있는 경우 BeginWrite/BeginRead 메서드를 사용하여 각각에 대해 새 스레드를 만들 필요없이 모두 처리 할 수 ​​있습니다.

다음은 서버에 연결하고 파일을 보내고 연결을 끊는 작은 예입니다. 그것은 열려있는 tcpclients의 양을 처리 할 수 ​​있습니다. 그리고 당신이 보는대로, 내가 그 제조에 사용되는 다른 포트를 보낼 경우

/// <summary> 
/// Thread safe queue of client ids 
/// </summary> 
internal class FileSender 
{ 
    /// <summary> 
    /// A write operation have completed 
    /// </summary> 
    /// <param name="ar"></param> 
    private void OnWriteCompleted(IAsyncResult ar) 
    { 
     // We passed the context to this method, cast it back 
     var context = (ClientContext) ar.AsyncState; 

     // end the write 
     context.TcpClient.GetStream().EndWrite(ar); 

     // we've completed. 
     if (context.BytesSent >= context.FileStream.Length) 
     { 
      // notify any listener 
      Completed(this, new CompletedEventArgs(context.RemoteEndPoint, context.FileStream.Name)); 
      context.TcpClient.Close(); 
      return; 
     } 

     // Send more data from the file to the server. 
     int bytesRead = context.FileStream.Read(context.Buffer, 0, context.Buffer.Length); 
     context.BytesSent += bytesRead; 
     context.TcpClient.GetStream().BeginWrite(context.Buffer, 0, bytesRead, OnWriteCompleted, context); 
    } 

    /// <summary> 
    /// Send a file 
    /// </summary> 
    /// <param name="endPoint"></param> 
    /// <param name="fullPath"></param> 
    public void SendFile(IPEndPoint endPoint, string fullPath) 
    { 
     // Open a stream to the file 
     var stream = new FileStream(fullPath, FileMode.Open, FileAccess.Read); 

     // Create a client and connect to remote end 
     var client = new TcpClient(); 
     client.Connect(endPoint); 

     // Context is used to keep track of this client 
     var context = new ClientContext 
          { 
           Buffer = new byte[65535], 
           FileStream = stream, 
           TcpClient = client, 
           RemoteEndPoint = endPoint 
          }; 

     // read from file stream 
     int bytesRead = stream.Read(context.Buffer, 0, context.Buffer.Length); 

     // and send the data to the server 
     context.BytesSent += bytesRead; 
     client.GetStream().BeginWrite(context.Buffer, 0, bytesRead, OnWriteCompleted, context); 
    } 

    /// <summary> 
    /// File transfer have been completed 
    /// </summary> 
    public event EventHandler<CompletedEventArgs> Completed = delegate { }; 

    #region Nested type: ClientContext 

    /// <summary> 
    /// Used to keep track of all open connections 
    /// </summary> 
    private class ClientContext 
    { 
     /// <summary> 
     /// Gets or sets buffer used to send file 
     /// </summary> 
     public byte[] Buffer { get; set; } 

     /// <summary> 
     /// Gets or sets number of bytes sent. 
     /// </summary> 
     public int BytesSent { get; set; } 

     /// <summary> 
     /// Gets or sets file to send 
     /// </summary> 
     public FileStream FileStream { get; set; } 

     public IPEndPoint RemoteEndPoint { get; set; } 

     /// <summary> 
     /// Gets or sets client sending the file 
     /// </summary> 
     public TcpClient TcpClient { get; set; } 
    } 

    #endregion 
} 

internal class CompletedEventArgs : EventArgs 
{ 
    public CompletedEventArgs(IPEndPoint endPoint, string fullPath) 
    { 
     EndPoint = endPoint; 
     FullPath = fullPath; 
    } 

    public IPEndPoint EndPoint { get; private set; } 
    public string FullPath { get; private set; } 
}