4

この質問をするのも恥ずかしいですが、グーグルで徹底的に検索した後(MSDNを使い始めました...)、投稿することにしました:

ちょうど今、クライアント サーバー プログラミング (C# を使用) の学習を開始し、tcpClient を使用して最初のコードを記述しようとしています。サーバー側とクライアント側の両方を書いています。これが私の質問です。常に、クライアントは 1 つの String をサーバーに送信し、サーバーは String をクライアントに送り返します。サーバーは 2 つの文字列を続けて送信できませんか? 彼はクライアントの応答を待つ必要がありますか? これはクライアントサーバーの原則ですか??

繰り返しますが、お粗末な質問で申し訳ありません。ありがとう...

<> 私のコードの一部 (長いコード...) を投稿してみます。冗長な部分を切り取ろうとしたので、コードが意味をなすことを願っています... (主な問題を//************でマークしました)

public class MServer2
{
Dictionary<String, String> nameAndPass = new Dictionary<String, String>();
Dictionary<String, List<String> > nameAndMail = new Dictionary<String, List<String>>();

public static void Main()
{
    new MServer2();
}

public MServer2()
{
    TcpListener server = new TcpListener(8500);
    try
    {
        server.Start();
        Console.WriteLine("started " + server);
        while (true)
        {
            TcpClient client = server.AcceptTcpClient();
            Console.WriteLine("connection accepted " + client);
            new Server1(client, nameAndPass, nameAndMail);
        }
    }
    catch (Exception e)
    {
        Console.WriteLine("exception" + e);
    }
    finally
    {
        server.Stop();
    }
}

class Server1
{
TcpClient client;
NetworkStream netStream;
Dictionary<String, String> nameAndPass1 = new Dictionary<String, String>();
Dictionary<String, List<String>> nameAndMail1 = new Dictionary<String, List<String>>();

internal Server1(TcpClient client, Dictionary<String, String> nameandPassFromFile, Dictionary<String, List<String> > nameAndMailsFromFile)
{
    nameAndPass1 = nameandPassFromFile;
    nameAndMail1 = nameAndMailsFromFile;

    this.client = client;
    Thread thr = new Thread(new ThreadStart(Run));
    thr.Start();
}

public void Run()
{
    try
    {
        netStream = client.GetStream();
        StreamReader reader = new StreamReader(netStream);
        StreamWriter writer = new StreamWriter(netStream);
        writer.AutoFlush = true;
        Console.WriteLine("beginning to receive loop");

        writer.WriteLine("Choose your user name.");
        strFromClient = reader.ReadLine();
        userName = strFromClient;

        writer.WriteLine("Choose your user password.");
        strFromClient = reader.ReadLine();

        password = strFromClient;

        writer.WriteLine("Do you want to see the list of email addresses? (y/n)");
        strFromClient = reader.ReadLine();

//***********************************************************************************
//HERE'S MY PROBLAM:
//HERE THE CLIENT WILL GET A STRING SHOWING HIS EMAILS, AND I WANT HIM TO GET ANOTHER     STRING ASKING "Do you want to add an email address? (y/n)", BUT IT LOOKS LIKE THE SERVER     "WAITS" FOR A RESPONSE FROM THE CLIENT TO SHOW THE NEXT STRING...
        if (strFromClient == "y")
        {   
            String tmpStr = null;
            List<String> tmp = nameAndMail1[userName];
            for(int i=0; i<nameAndMail1[userName].Count; i++)
            {
                tmpStr += tmp[i] + " ";
            }

            writer.WriteLine(tmpStr);                            
        } 
        writer.WriteLine("Do you want to add an email address? (y/n)");
        strFromClient = reader.ReadLine();

    }    

}
    catch (Exception e)
    {
        Console.WriteLine("{0} Exception caught.", e);
    }

編集 VOL 2

わかった!2 時間の惨めさの後、Phil Frost (天才!) のおかげで問題を発見したと思います--- 問題はおそらくクライアントにあります... (Im soch a-hole!)。

サーバーは2つの文字列を連続して送信しますが、クライアント側の私の愚かな実装は、クライアントから送信されたメッセージに従わないメッセージ(サーバーから受信したメッセージ)を表示しません...

だからもう一度あなたの助けが必要です。クライアント フォームをどのように設計したかを次に示します。 ここに画像の説明を入力

私の経験不足により、「サーバーに接続」ボタンが押されたときにサーバーに接続し、「メッセージを送信」ボタンが押されたときにのみサーバーからのメッセージが表示されました。問題は、クライアントからサーバーにメッセージを送信せずに、サーバーから 2 つ (またはそれ以上) のメッセージを受信した場合です。クライアントは、新しいメッセージが受信されたことを認識していません! サーバーからのメッセージをどこで受信すると思いますか? (「where」は、たとえば、どの関数の下であるかを意味します-現在、sendMessage_click関数で発生します)。

これまでのすべてのヘルプにもう一度感謝します!!

4

3 に答える 3

6

この質問はお粗末でも些細なことでもありません。あなたはプロトコル設計の重要なポイントに触れています。

AFAIK、この特定の猫の皮を剥ぐには2つの方法があります。

  • 「ダイアログ」(あなたのやり方)...リクエストの後に返信が続き、次のリクエストが続きます。これには簡単であるという大きな利点がありますが、接続ごとに1つのコマンドしか処理されないという大きな欠点があります。
  • 「非同期」(どちらの当事者も応答を待たずに送信できます)...これには実装上の問題があり、どの応答がどの要求に属しているかを知ることができるようにするために、ある種の要求IDが必要です。クライアントが送信することを想像してください。 2つのリクエスト。最初のリクエストは2番目のリクエストよりも処理に時間がかかります。返信はリクエストとは異なる順序になります。

これらのバリアント間の選択は必ずしも簡単なものではありませんが、トレンドは非同期モデルに向かっています。

非同期フレーバーのその他の問題には、一度に1つのメッセージのみが送信されることを確認するメカニズム(メッセージを織り交ぜると、解析できないストリームが発生する可能性が高い)とタイムアウトの考慮事項が含まれます。

于 2012-12-31T14:53:05.837 に答える
2

はい、サーバーは2つの文字列を続けて送信できます。ただし、サーバーがでブロックされている場合はおそらくそうではありませんread()。おそらく、プログラムについてさらに詳細を含めると、より具体的な回答が提供される可能性があります。

于 2012-12-31T14:49:26.580 に答える
1

TCP では、クライアントからサーバーへのチャネルとサーバーからクライアントへのチャネルは 2 つの独立したストリームです。どちらの当事者もいつでも送信できます。

于 2012-12-31T14:48:26.763 に答える