2

私は完全な書面による解決策を探しているのではなく、学校の課題の一部であるため、何が問題になっているのかを知りたいだけです。どちらのクラスも先生が書いているので、パソコンの調子が悪いと思いますが、どこを見ればいいのかわかりません。他のいくつかの解決策を検索しましたが、低レベルの解決策を除いて、これと異なるものは見つかりませんでしたが、教師から低レベルの解決策も入手しましたが、それも機能しません。

サーバー:

var ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
TcpListener server = new TcpListener(ipAddress, clientPort);
server.Start();
TcpClient client = server.AcceptTcpClient(); // The server gets here
StreamReader clientIn = new StreamReader(client.GetStream());
StreamWriter clientOut = new StreamWriter(client.GetStream());
clientOut.AutoFlush = true;
while (true)
{
    string msg = clientIn.ReadLine();
    Console.WriteLine(msg);
    clientOut.WriteLine(msg);  
}

クライアント:

TcpClient client = new TcpClient("localhost", serverPort); //The client gets here
StreamReader clientIn = new StreamReader(client.GetStream());
StreamWriter clientOut = new StreamWriter(client.GetStream());

clientOut.AutoFlush = true;

while (true)
{
    clientOut.WriteLine(Console.ReadLine());
    Console.WriteLine(clientIn.ReadLine());
}

クライアントはtry-catchブロックにあり、接続が確立されるまでループしているため、サーバーへの接続を何度も試行します。AcceptTcpClientは接続を待機するだけなので、サーバーはキャッチされませんが、同じIP上にあり、他のプロセスのポート上にある間は、接続に到達することはありません。

接続は別々のスレッドで開始されますが、メインスレッドは接続が終了するまで待機しているようです。これは私が期待したことではありません。私は両方をさまざまな方法でスリープさせようとしましたが(ドキュメントにThread.Sleep(1000)Thread.Sleep(0)、そうすると別のスレッドがスケジュールされると書かれていwhile(stopwatch<1000ms) {for(i<100000)}ました)、どちらも役に立ちませんでした。メインスレッドは、接続スレッドのスリープがなくなり、接続スレッドが再びクライアントを作成した時点で、ある程度の進歩しかありません。

この問題は、別のW764ビットコンピューターでも発生します。

誰かが問題が何であるか知っていますか?

4

1 に答える 1

4

IPAddress.Any問題は、サーバーを構築するときに使用しているという事実にほぼ確実にあります。それが問題になる理由は、それが必ずしも解決されるとは限らないためlocalhostです。幸運になるかもしれませんが、一貫性はありません。したがって、次のようなIPアドレスでサーバーを起動することをお勧めします。

var ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
TcpListener server = new TcpListener(ipAddress, clientPort);

次に、これを行っていると確信していますが、ポートがとの両方clientPortで同じであることを確認してくださいserverPort

次に、while (true)ループは私には非常に疑わしいので、以下の例ではそれを変更します。不可能でない限り、常に避けてくださいwhile (true)、あなたは文字通り問題を物乞いしています。

最後に、ここでスレッド化を行う方法を取り巻くと、どういうわけか2つの別々のスレッドを構築する必要があり、BackgroundWorkerクラスをお勧めします(他の人がお勧めするかもしれませんが、それについてはまだ十分async-awaitわかりません。 .NET 4.5を使用する必要がありますが、使用しているかどうかはわかりません)。

したがって、BackgroundWorkerサーバー用に次のようなものを作成できます(そして、クライアント用に同様の別のものを作成できます)。

var worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.WorkerSupportsCancellation = true;

worker.ProgressChanged += (s, args) =>
{
    Console.WriteLine(args.UserState);
}

worker.DoWork += (s, args) =>
{
    // startup the server on localhost
    var ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
    TcpListener server = new TcpListener(ipAddress, clientPort);
    server.Start();

    while (!worker.CancellationPending)
    {
        // as long as we're not pending a cancellation, let's keep accepting requests
        TcpClient client = server.AcceptTcpClient();

        StreamReader clientIn = new StreamReader(client.GetStream());
        StreamWriter clientOut = new StreamWriter(client.GetStream());
        clientOut.AutoFlush = true;

        while ((string msg = clientIn.ReadLine()) != null)
        {
            worker.ReportProgress(1, msg);  // this will fire the ProgressChanged event
            clientOut.WriteLine(msg);
        }
    }
}

RunWorkerAsync最後に、次のように呼び出すことで、これらのワーカーを起動する必要があります。

worker.RunWorkerAsync();

アップデート

了解しました。以下は、2104に接続する完全に機能するコンソールアプリケーションです。注意する必要があるのは、使用時にvar ipAddress = Dns.GetHostEntry("localhost").AddressList[0];次のようなIPアドレスを取得することです。これ::1が問題です。ただし、クライアントでリッスン127.0.0.1:2104すると、を発行するときに接続しようとしているものがvar result = client.BeginConnect("localhost", 2104, null, null);、を発行するのと同じであるため、接続できますnew TcpClient("localhost", 2104);

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net.Sockets;
using System.ComponentModel;
using System.Threading;
using System.Net;

namespace ConsoleApplication13
{
    class Program
    {
        static void Main()
        {
            var worker = new BackgroundWorker();
            worker.WorkerReportsProgress = true;
            worker.WorkerSupportsCancellation = true;

            worker.ProgressChanged += (s, args) =>
            {
                Console.WriteLine(args.UserState);
            };

            worker.DoWork += (s, args) =>
            {
                // startup the server on localhost 
                var ipAddress = IPAddress.Parse("127.0.0.1");
                TcpListener server = new TcpListener(ipAddress, 2104);
                server.Start();

                while (!worker.CancellationPending)
                {
                    Console.WriteLine("The server is waiting on {0}:2104...", ipAddress.ToString());

                    // as long as we're not pending a cancellation, let's keep accepting requests 
                    TcpClient attachedClient = server.AcceptTcpClient();

                    StreamReader clientIn = new StreamReader(attachedClient.GetStream());
                    StreamWriter clientOut = new StreamWriter(attachedClient.GetStream());
                    clientOut.AutoFlush = true;

                    string msg;
                    while ((msg = clientIn.ReadLine()) != null)
                    {
                        Console.WriteLine("The server received: {0}", msg);
                        clientOut.WriteLine(string.Format("The server replied with: {0}", msg));
                    }
                }
            };

            worker.RunWorkerAsync();

            Console.WriteLine("Attempting to establish a connection to the server...");

            TcpClient client = new TcpClient();

            for (int i = 0; i < 3; i++)
            {
                var result = client.BeginConnect("localhost", 2104, null, null);

                // give the client 5 seconds to connect
                result.AsyncWaitHandle.WaitOne(5000);

                if (!client.Connected)
                {
                    try { client.EndConnect(result); }
                    catch (SocketException) { }

                    string message = "There was an error connecting to the server ... {0}";

                    if (i == 2) { Console.WriteLine(message, "aborting"); }
                    else { Console.WriteLine(message, "retrying"); }

                    continue;
                }

                break;
            }

            if (client.Connected)
            {
                Console.WriteLine("The client is connected to the server...");

                StreamReader clientIn = new StreamReader(client.GetStream());
                StreamWriter clientOut = new StreamWriter(client.GetStream());

                clientOut.AutoFlush = true;

                string key;
                while ((key = Console.ReadLine()) != string.Empty)
                {
                    clientOut.WriteLine(key);
                    Console.WriteLine(clientIn.ReadLine());
                }
            }
            else { Console.ReadKey(); }
        }
    }
}
于 2012-10-18T11:31:09.913 に答える