0

サーバーとクライアントの 2 つの部分で構成されるチャット プログラムをコーディングしてきました。サーバーはTcpListener、サーバーに参加するための着信要求をリッスンするために使用し、クライアントはTcpClientそれを使用してサーバーに接続し、メッセージを送信します。これまでのところ、クライアントが接続したときに送信される最初のメッセージであるハンドシェイクがあります。これには、クライアントの IP アドレスとニックネーム セットが含まれています。サーバーが非同期でリッスンするようにする方法がわかりません。非同期でない場合、チャットはclient -> server -> client -> server一度に複数のクライアントに接続し、一度に複数のメッセージを受信する必要があるためです。これまでの私のコードは同期的に書かれています:
クライアント:

public void StartClient(string serverIP)
{
    ReadWrite rw = new ReadWrite();
    string nick = rw.GetNick();
    string handshakeContents = "HANDSHAKE:" + nick + ":" + GetIP();
    Int32 serverPort = 1336; // yay
    TcpClient client = new TcpClient(serverIP, serverPort);
    Console.WriteLine("Sending initial handshake: {0}", handshakeContents);
    Byte[] data = System.Text.Encoding.ASCII.GetBytes(handshakeContents); // Convert handshakeContents to Byte[]
    NetworkStream stream = client.GetStream(); // Instantiate object "stream" for use in read/write
    stream.Write(data, 0, data.Length); // Send handshakeContents in Byte[] to server
    Console.WriteLine(" - Connecting to IlanChat Server on ip {0}", serverIP);
    Thread.Sleep(1000); // sleep 1s
    data = new Byte[256];
    string responseHandshake = String.Empty; // response handshake from server
    Int32 bytes = stream.Read(data, 0, data.Length); // Read handshake.
    responseHandshake = System.Text.Encoding.ASCII.GetString(data, 0, bytes); // Decode from Byte[] to ASCII string
    Console.WriteLine(" -  Received response handshake: {0}", responseHandshake);
    Console.WriteLine(" - Successfully connected to IlanChat server on IP {0}", serverIP); // display message
    Thread.Sleep(2000);
    Console.Clear();
    List<string> messagesRecieved = new List<string>();
    while(true)
    {
        Console.Clear();
        foreach (string msg in messagesRecieved)
        {
            Console.WriteLine(msg);
        }
        Console.WriteLine();
        Console.Write("Enter message: ");
        string msgRaw = Console.ReadLine();
        string sendMsg = nick + ": " + msgRaw;
        data = new Byte[256];
        data = System.Text.Encoding.ASCII.GetBytes(sendMsg);
        stream.Write(data, 0, data.Length); // finish this async shit
    }
}

サーバ:

        List<string> clientIP = new List<string>();
        List<string> clientNicks = new List<string>();
        string responseHandshake = "hello";
        Int32 serverPort = 1336;
        IPAddress machineIP = IPAddress.Parse(GetIP());
        Console.Clear();
        Console.WriteLine(" - Starting IlanChat server on IP {0}", machineIP);
        TcpListener server = null;
        server = new TcpListener(machineIP, serverPort);
        server.Start();
        Byte[] buffer = new Byte[256];
        String data = null;
        Console.WriteLine("Successfully started IlanChat server!");
        while (true) // first alpha - only one user at a time
        {
            Console.WriteLine();
            Console.WriteLine("Waiting for connections..");
            TcpClient client = server.AcceptTcpClient();
            Console.WriteLine("User connecting..");
            Console.WriteLine("Receiving handshake data..");
            data = null;
            NetworkStream stream = client.GetStream();
            int i;
            while ((i = stream.Read(buffer, 0, buffer.Length)) != 0)
            {
                data = System.Text.Encoding.ASCII.GetString(buffer, 0, i);
                Console.WriteLine("Received handshake data: {0}", data);
                Console.WriteLine("Processing data.."); // sample handshake: - HANDSHAKE:nick:ip
                string tempNick = data.Replace("HANDSHAKE:", "");
                string[] userDetails = tempNick.Split(':'); // should store to 0:nick, 1:ip
                Console.WriteLine("Received client nick: {0}", userDetails[0]);
                Console.WriteLine("Received client IP: {0}", userDetails[1]);
                break;
            }
            Thread.Sleep(1100); // sleep
            buffer = System.Text.Encoding.ASCII.GetBytes(responseHandshake);
            Console.WriteLine("Sending response handshake..");
            stream.Write(buffer, 0, buffer.Length);
        }

サーバーが一度に複数の接続を受け入れ、それらを維持する方法はありますか? また、クライアントに一度に複数のメッセージを受信させ、メッセージを更新しながら入力させる方法はありますか?

4

1 に答える 1

1

必要なことを行うには、スレッド化 (タスク ライブラリ、async/await) の使用を検討する必要があります。ここを見てみてください:

https://codereview.stackexchange.com/questions/29000/c-console-chat-server-async-await-tcpclient-tcplistener-networkstream-asyn

開始するには、コードのロジックが正しいと仮定して、次のようにサーバー/クライアントを分割します。

static void RunServer()
        {
            List<string> clientIP = new List<string>();
            List<string> clientNicks = new List<string>();
            string responseHandshake = "hello";
            Int32 serverPort = 1336;
            IPAddress machineIP = IPAddress.Parse(GetIP());
            Console.Clear();
            Console.WriteLine(" - Starting IlanChat server on IP {0}", machineIP);
            TcpListener server = null;
            server = new TcpListener(machineIP, serverPort);
            server.Start();
            Byte[] buffer = new Byte[256];
            String data = null;
            Console.WriteLine("Successfully started IlanChat server!");
            while (true) // first alpha - only one user at a time
            {
                Console.WriteLine();
                Console.WriteLine("Waiting for connections..");
                TcpClient client = server.AcceptTcpClient();

                Task.Run(() => RunClient(client));
            }
        }

        static void RunClient(TcpClient client)
        {
            Byte[] buffer = new Byte[256];
            Console.WriteLine("User connecting..");
            Console.WriteLine("Receiving handshake data..");
            String data = null;
            string responseHandshake = "hello";

            NetworkStream stream = client.GetStream();
            int i;
            while ((i = stream.Read(buffer, 0, buffer.Length)) != 0)
            {
                data = System.Text.Encoding.ASCII.GetString(buffer, 0, i);
                Console.WriteLine("Received handshake data: {0}", data);
                Console.WriteLine("Processing data.."); // sample handshake: - HANDSHAKE:nick:ip
                string tempNick = data.Replace("HANDSHAKE:", "");
                string[] userDetails = tempNick.Split(':'); // should store to 0:nick, 1:ip
                Console.WriteLine("Received client nick: {0}", userDetails[0]);
                Console.WriteLine("Received client IP: {0}", userDetails[1]);
                break;
            }
            Thread.Sleep(1100); // sleep
            buffer = System.Text.Encoding.ASCII.GetBytes(responseHandshake);
            Console.WriteLine("Sending response handshake..");
            stream.Write(buffer, 0, buffer.Length);
        }
于 2013-11-11T10:32:29.883 に答える