7

私はソケットプログラミングについて少し学ぼうとしています.TcpListenerとTcpClientを見つけたので、初心者にとっては少し簡単です。私が達成したいことの基本的な要点は、同じネットワーク上の私のラップトップと別のラップトップで実行できる小さなフォームを作成し、それらが通信できるようにすることです。つまり、テキストの文字列を互いに送信します。これを手に入れたら、うまくいけばそれをさらに発展させます:)

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

    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);

それが最もきちんとした解決策であるかどうかはわかりませんが、うまく機能しているので、答えてくれてありがとう:)

4

2 に答える 2

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 チャットの例を確認してください。

于 2013-02-12T17:57:09.880 に答える
1

接続先のコンピューターの名前がわかっている場合は、System.Net.DNS を使用してその IP を簡単に見つけることができます。

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

使用していると思われる IP は、その配列のロケーション 0 のものではない可能性があるため、注意してください。

于 2013-02-12T18:01:17.457 に答える