2013-02-12 28 views
6

我想了解一些关于套接字编程,我偶然发现TcpListener和TcpClient使用,因为我读它们对初学者来说稍微容易一些。 我想要完成的基本任务是制作一个小型表单,可以在我的笔记本电脑和另一台笔记本电脑上运行,并且可以进行通信,即发送一串文本给对方。一旦我有这个,我会希望进一步发展:)设置一个TCP/IP客户端和服务器通过网络进行通信

到目前为止,我创建了一个客户端和服务器程序使用msdn和各种指南在互联网上找到。当我在一台笔记本电脑上运行时,我可以让他们进行通信,但当我将客户端移动到另一台笔记本电脑时,我无处可去。我认为我的主要问题是我不太了解客户端如何找到服务器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); 

我不知道这是否是最巧妙的解决方案,但它运作良好,所以,谢谢你的答案:)

+1

如果你正在寻找一个通用的代码审查,我会建议发布到[CodeReview.SE](http://codereview.stackexchange.com/)。如果您正在寻找特定问题的答案(“是否有任何方式让二者以更动态的方式连接以涵盖不断变化的IP?”),那么您应该将代码缩小到您所在的区域有问题。 – Bobson 2013-02-12 17:51:49

+0

道歉Bobson我将在未来保持我的代码片段更短,更相关!感谢您的建议:) – 2013-02-13 09:29:42

回答

1

不太清楚你的意思是“更动态的方式来包含变化的IP”。以一个猜测,你目前有首发:如果他们在不同的机器上运行

IPAddress.Parse("127.0.0.1") 

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

您可以运行在同一台机器上的两个客户端&服务器,并使用本地回送IP地址只需用服务器正在使用的任何IP地址替换127.0.0.1即可(这种方式假定没有NAT或防火墙)。

如果你不希望使用IP地址,你总是可以使用主机名(这可能被认为是更“动态”),但是这需要一个适当配置的DNS设置(本地系统):

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

学习套接字编程很棒。我是一个网络图书馆networkcomms.net的开发者,所以你也应该在学习自己的同时,从工作示例中倒退,请检查这个wpf chat example

+0

非常感谢您,正如我在编辑中看到的,我已经使用主机名来获取IP并指出了这一点。欢呼声指向我正确的方向,我一定会看看你的工作示例,以了解更多! – 2013-02-13 09:31:12

1

如果您知道要连接的计算机的名称,则可以使用System.Net.DNS轻松找到其IP。

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

您认为您使用的IP可能不是该阵列的位置0中的那个IP,所以请注意这一点。

+0

谢谢你的帮助我也在我的解决方案中使用了你的建议,我想我已经实现了一种方法来确保我从AddressList中获得正确的IP,你可以在我的编辑中看到我的尝试:) – 2013-02-13 09:34:23

相关问题