设置TCP / IP客户端和服务器以通过网络进行通信

时间:2013-02-12 17:38:31

标签: c# .net winforms tcp client-server

我正在尝试学习一些关于套接字编程的知识,我偶然发现了TcpListener和TcpClient,因为我读到它们对初学者来说稍微容易一些。 我想要完成的基本要点是拥有一个小型表格,可以在我的笔记本电脑和同一网络上的另一台笔记本电脑上运行,并让他们能够进行通信,即相互发送一串文字。有了这个,我希望能进一步发展它:)

到目前为止,我已经使用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);

我不确定它是否是最好的解决方案,但效果很好,所以谢谢你的答案:)

2 个答案:

答案 0 :(得分:1)

不太确定你的意思是'更有活力的方式来包含改变的ip'。猜猜你现在的初学者:

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

您可以同时运行客户端和服务器在同一台机器上并使用本地环回IP地址:

IPAddress.Parse("127.0.0.1")

如果它们在不同的计算机上运行,​​只需将127.0.0.1替换为服务器正在使用的任何IP地址(假设没有NAT或防火墙)。

如果您不想使用IP地址,您可以始终使用主机名(这些可能被认为更“动态”)但这需要适当配置的DNS设置(对于本地系统):

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

学习套接字编程真是太棒了。我是网络图书馆networkcomms.net的开发者,所以如果你想学习自己的同时也想从工作实例中反向工作,请查看wpf chat example

答案 1 :(得分:1)

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

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

您认为正在使用的IP可能不是该阵列的0位置,因此请注意。