0
static void Main(string[] args)
    {
        Console.Title = "Socket Server";
        Console.WriteLine("Listening for client messages");

        Socket serverSocket = new Socket(AddressFamily.InterNetwork,
                                         SocketType.Stream,
                                         ProtocolType.Tcp);
        IPAddress serverIp = IPAddress.Any;
        IPEndPoint serverEP = new IPEndPoint(serverIp, 8000);

        SocketPermission socketPermission = new SocketPermission(NetworkAccess.Accept,
                                                                 TransportType.Tcp,
                                                                 "127.0.0.1", 8000);

        serverSocket.Bind(serverEP);
        serverSocket.Listen(2);


        while(true)
        {
            //Socket connection = serverSocket.Accept();

            connection = serverSocket.Accept();

            Thread clientThread = new Thread(new ParameterizedThreadStart(MultiUser));           
            clientThread.Start(connection);


        }
    }

    public static void MultiUser(object connection)
    {

        byte[] serverBuffer = new byte[10025];
        string message = string.Empty;

        int bytes = ((Socket)connection).Receive(serverBuffer, serverBuffer.Length, 0);
        message += Encoding.ASCII.GetString(serverBuffer, 0, bytes);
        Console.WriteLine(message);

        TcpClient client = new TcpClient();
        client.Client = ((Socket)connection);
        IntPtr handle = client.Client.Handle;



    }

1 つのサーバーと 2 つのクライアントを持つチャット プログラムを作成したいと考えています。問題は、client1 から送信されたメッセージをサーバー経由で client2 に送信できないことです。サーバーは、受信したメッセージを client1 から client2 に送信できるように、どのようにスレッドを区別できますか?

4

1 に答える 1

1

各クライアントには独自のハンドルがあります。これには、 Handleプロパティを介してアクセスできます。例えば:

TcpClient client = tcpListener.AcceptTcpClient();
IntPtr handle = client.Client.Handle; //returns a handle to the connection

あとは、これをハッシュテーブルに格納し、利用可能なデータを探して反復するだけです。いずれかの接続のワイヤ上にデータを検出したら、それを保存して、テーブル内の他のクライアントに再送信します。

これをマルチスレッド化することを忘れないでください。これにより、1 つのクライアントでのリッスン要求が、他のクライアントでの送信または受信機能をブロックしないようになります。

ここに、作業できるはずのコードをいくつか追加しました(私のシステムでテストしました)

private void HandleClients(object newClient)
        {
            //check to see if we are adding a new client, or just iterating through existing clients
            if (newClient != null)
            {
                TcpClient newTcpClient = (TcpClient)newClient;

                //add this client to our list
                clientList.Add(newTcpClient.Client.Handle, newTcpClient);
                Console.WriteLine("Adding handle: " + newTcpClient.Client.Handle);  //for debugging
            }

            //iterate through existing clients to see if there is any data on the wire
            foreach (TcpClient tc in clientList.Values)
            {
                if (tc.Available > 0)
                {
                    int dataSize = tc.Available;
                    Console.WriteLine("Received data from: " + tc.Client.Handle); //for debugging

                    string text = GetNetworkString(tc.GetStream());

                    //and transmit it to everyone else
                    foreach (TcpClient otherClient in clientList.Values)
                    {
                        if (tc.Client.Handle != otherClient.Client.Handle)
                        {
                            Send(otherClient.GetStream(), text);
                        }
                    }
                }
            }
        }

        public void Send(NetworkStream ns, string data)
        {
            try
            {
                byte[] bdata = GetBytes(data, Encoding.ASCII);
                ns.Write(bdata, 0, bdata.Length);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
            }
        }

        protected string GetNetworkString(NetworkStream ns)
        {
            if (ns.CanRead)
            {
                string receivedString;
                byte[] b = GetNetworkData(ns);

                receivedString = System.Text.Encoding.UTF8.GetString(b);
                log.Info("Received string: " + receivedString);

                return receivedString;
            }
            else
                return null;
        }

        protected byte[] GetNetworkData(NetworkStream ns)
        {
            if (ns.CanRead)
            {
                log.Debug("Data detected on wire...");
                byte[] b;
                byte[] myReadBuffer = new byte[1024];
                MemoryStream ms = new MemoryStream();
                int numberOfBytesRead = 0;

                // Incoming message may be larger than the buffer size.
                do
                {
                    numberOfBytesRead = ns.Read(myReadBuffer, 0, myReadBuffer.Length);
                    ms.Write(myReadBuffer, 0, numberOfBytesRead);
                }
                while (ns.DataAvailable);

                //and get the full message
                b = new byte[(int)ms.Length];
                ms.Seek(0, SeekOrigin.Begin);
                ms.Read(b, 0, (int)ms.Length);
                ms.Close();

                return b;
            }
            else
                return null;
        }

保留中の要求があるかどうかを確認し、ループで実行するメイン スレッドからHandleClientsを呼び出す必要があります。

于 2012-12-21T20:46:42.277 に答える