2013-02-12 16 views
6

ソケットプログラミングについて少し勉強しようとしていますが、TcpListenerとTcpClientを使いこなすのはちょっと難しすぎます。 私が達成したいことの基本的な話は、同じネットワーク上のラップトップと別のラップトップで実行できる小さなフォームを持ち、それらが通信できるように、すなわち互いに文字列を送信することです。私がこれを持っていれば、それをさらに発展させることができます:)ネットワークを介して通信するためのTCP/IPクライアントとサーバーの設定

これまで、私はmsdnとインターネット上のさまざまなガイドを使ってクライアントプログラムとサーバープログラムを作成しました。 1台のラップトップで走っているときでも、別のラップトップにクライアントを移動させてもどこにもいないときに、私はそれらに通信することができます。私の主な問題は、クライアントがサーバーIPを見つけたのはどういうものなのか分かりませんと思うのですが、ハードコーディングが可能だと思いますが、別の時に戻ったときにIPが変わったと確信しています。変化するIPを取り囲むように、より動的な方法で接続する方法はありますか? 私の現在のクライアントコード:

public void msg(string mesg) 
    { 
     lstProgress.Items.Add(">> " + mesg); 
    } 

    private void btnConnect_Click(object sender, EventArgs e) 
    { 
     string message = "Test"; 
     try 
     { 
      // Create a TcpClient. 
      // Note, for this client to work you need to have a TcpServer 
      // connected to the same address as specified by the server, port 
      // combination. 
      Int32 port = 1333; 
      TcpClient client = new TcpClient(<not sure>, port); //Unsure of IP to use. 

      // Translate the passed message into ASCII and store it as a Byte array. 
      Byte[] data = System.Text.Encoding.ASCII.GetBytes(message); 

      // Get a client stream for reading and writing. 
      // Stream stream = client.GetStream(); 

      NetworkStream stream = client.GetStream(); 

      // Send the message to the connected TcpServer. 
      stream.Write(data, 0, data.Length); 

      lstProgress.Items.Add(String.Format("Sent: {0}", message)); 

      // Receive the TcpServer.response. 

      // Buffer to store the response bytes. 
      data = new Byte[256]; 

      // String to store the response ASCII representation. 
      String responseData = String.Empty; 

      // Read the first batch of the TcpServer response bytes. 
      Int32 bytes = stream.Read(data, 0, data.Length); 
      responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes); 
      lstProgress.Items.Add(String.Format("Received: {0}", responseData)); 

      // Close everything. 
      stream.Close(); 
      client.Close(); 
     } 
     catch (ArgumentNullException an) 
     { 
      lstProgress.Items.Add(String.Format("ArgumentNullException: {0}", an)); 
     } 
     catch (SocketException se) 
     { 
      lstProgress.Items.Add(String.Format("SocketException: {0}", se)); 
     } 
    } 

私の現在のサーバーコード:

private void Prog_Load(object sender, EventArgs e) 
    { 
     bw.WorkerSupportsCancellation = true; 
     bw.WorkerReportsProgress = true; 
     bw.DoWork += new DoWorkEventHandler(bw_DoWork); 
     bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged); 

     if (bw.IsBusy != true) 
     { 
      bw.RunWorkerAsync(); 
     } 
    } 

    private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e) 
    { 
     lstProgress.Items.Add(e.UserState); 
    } 

    private void bw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     BackgroundWorker worker = sender as BackgroundWorker; 

     if ((worker.CancellationPending == true)) 
     { 
      e.Cancel = true; 
     } 
     else 
     { 
      try 
      { 
       // Set the TcpListener on port 1333. 
       Int32 port = 1333; 
       //IPAddress localAddr = IPAddress.Parse("127.0.0.1"); 
       TcpListener server = new TcpListener(IPAddress.Any, port); 

       // Start listening for client requests. 
       server.Start(); 

       // Buffer for reading data 
       Byte[] bytes = new Byte[256]; 
       String data = null; 

       // Enter the listening loop. 
       while (true) 
       { 
        bw.ReportProgress(0, "Waiting for a connection... "); 
        // Perform a blocking call to accept requests. 
        // You could also user server.AcceptSocket() here. 
        TcpClient client = server.AcceptTcpClient(); 
        bw.ReportProgress(0, "Connected!"); 

        data = null; 

        // Get a stream object for reading and writing 
        NetworkStream stream = client.GetStream(); 

        int i; 

        // Loop to receive all the data sent by the client. 
        while ((i = stream.Read(bytes, 0, bytes.Length)) != 0) 
        { 
         // Translate data bytes to a ASCII string. 
         data = System.Text.Encoding.ASCII.GetString(bytes, 0, i); 
         bw.ReportProgress(0, String.Format("Received: {0}", data)); 

         // Process the data sent by the client. 
         data = String.Format("I Have Received Your Message: {0}", data); 

         byte[] mssg = System.Text.Encoding.ASCII.GetBytes(data); 

         // Send back a response. 
         stream.Write(mssg, 0, mssg.Length); 
         bw.ReportProgress(0, String.Format("Sent: {0}", data)); 
        } 

        // Shutdown and end connection 
        client.Close(); 
       } 
      } 
      catch (SocketException se) 
      { 
       bw.ReportProgress(0, String.Format("SocketException: {0}", se)); 
      } 
     } 
    } 

これを実装するためのより良い方法がある場合、私はより多くの午前ので、あなたはおそらく、私がこれまで新ブランド午前言うことができるように幸せに学ぶ!事前に任意の助け 感謝:)

私の解決策以下の答えのおかげで:

private String IPAddressCheck() 
    { 
     var IPAddr = Dns.GetHostEntry("HostName"); 
     IPAddress ipString = null; 

     foreach (var IP in IPAddr.AddressList) 
     { 
      if(IPAddress.TryParse(IP.ToString(), out ipString) && IP.AddressFamily == AddressFamily.InterNetwork) 
      { 
       break; 
      } 
     } 
     return ipString.ToString(); 
    } 

    private void btnConnect_Click(object sender, EventArgs e) 
    { 
     string message = "Test"; 
     try 
     { 
      Int32 port = 1337; 
      string IPAddr = IPAddressCheck(); 
      TcpClient client = new TcpClient(IPAddr, port); 

私はそれがneatestソリューションであるかどうかわからないんだけど、それがうまく機能しているので答えてくれてありがとう:)

+1

一般的なコードレビューをお探しの場合は、代わりに[CodeReview.SE](http://codereview.stackexchange.com/)に投稿することをおすすめします。特定の質問に対する回答を探している場合(「変化するIPを取り囲むように2人を動的につなぐ方法はありますか?」)、コードをあなただけの領域に縮小する必要があります問題がある – Bobson

+0

申し訳ありませんボブソン私は自分のコードスニペットをより短く、将来的にはより適切に保ちます!アドバイスありがとう:) –

答えて

1

「変化するIPを取り囲むためのよりダイナミックな方法」という言い方がよく分かりません。彼らは異なるマシン上で実行されている場合は

IPAddress.Parse("127.0.0.1") 

TcpClient client = new TcpClient(<not sure>, port); //Unsure of IP to use. 

あなたはローカルループバックIPアドレスを同じマシン上で両方のクライアント&サーバーを実行して使用することができます:あなたが現在持っている初心者のための推測を取ります127.0.0.1を、サーバが使用しているどのIPアドレスで置き換えてもかまいません(これは、途中でNATやファイアウォールがないことを前提としています)。

あなたは常にホスト名を使用することができます(これらは、より「動的」と見なされるかもしれない)が、これは(ローカルシステム用)適切に構成されたDNSの設定が必要となるIPアドレスを使用しない場合:

TcpClient client = new TcpClient("testMachine1", 1333); 

ソケットプログラミングを学ぶことは素晴らしいことです。私はネットワークライブラリnetworkcomms.netの開発者ですので、自分自身を学習するのと同時に作業例から逆に作業したい場合は、このwpf chat exampleをチェックアウトしてください。

+0

私の編集では、私はIPを取得し、それを指すためにホスト名を使用しているように私は編集で見ていただきありがとうございます。正しい方向に私を指差してくれてうれしく思います。私は間違いなくあなたの仕事の例を見て、もう少し学びます! –

1

接続したいコンピュータの名前を知っていれば、System.Net.DNSで簡単にIPを見つけることができます。

var ip = System.Net.Dns.GetHostEntry("JacksLaptop"); 
string ipString = ip.AddressList[0].ToString(); 

あなたが使用していると思われるIPは、その配列の位置0のものではない可能性があるので注意してください。

+0

あなたの助けてくれてありがとう私は私のソリューションであなたのアドバイスを使用して、私は私が私の編集で私の試行を見ることができるAddressListから正しいIPを得るための方法を実装したと思うopに編集:) –

関連する問題