1

私はプログラミングが初めてで、非同期クライアント サーバー アプリケーションに取り組んでいます。クライアントからサーバーにメッセージを送信できますが、サーバーにデータを受信し (OnDataReceived メソッド)、同じデータをクライアントに送信しようとすると (テスト目的で)、送信できません。他にどのような情報を提供する必要があるかわからないので、お知らせください。曖昧にするつもりはありません。

サーバーコード

public void OnDataReceived(IAsyncResult asyncResult)
    {
        try
        {
            SocketPacket socketData = (SocketPacket)asyncResult.AsyncState;
            int iRx = 0;
            iRx = socketData.currentSocket.EndReceive(asyncResult);
            char[] chars = new char[iRx];
            Decoder decoder = Encoding.UTF8.GetDecoder();
            int charLen = decoder.GetChars(socketData.dataBuffer, 0, iRx, chars, 0);
            String receivedData = new String(chars);

            //BroadCast(receivedData);

            this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() => lbxMessages.Items.Add(receivedData)));

            //Updated Code
            this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() => broadcast(receivedData)));

            WaitForData(socketData.currentSocket);


        }
        catch (ObjectDisposedException)
        {
            System.Diagnostics.Debugger.Log(0, "1", "\n OnDataRecieved: Socket has been closed\n");
        }
        catch (SocketException se)
        {
            MessageBox.Show(se.Message);
        }
    }

public class SocketPacket
    {
        public Socket currentSocket;
        public byte[] dataBuffer = new byte[50];//allowing the 50 digist to be sent at once
    }

    private void WaitForData(Socket socket)
    {
        try
        {
            if (workerCallBack == null)
            {
                workerCallBack = OnDataReceived;
            }
            SocketPacket sckPack = new SocketPacket();
            sckPack.currentSocket = socket;
            socket.BeginReceive(sckPack.dataBuffer, 0, sckPack.dataBuffer.Length, SocketFlags.None, workerCallBack, sckPack);
        }
        catch(SocketException se)
        {
            MessageBox.Show(se.Message);
        }
    }

アンドリューの返信に応じて更新

クライアントが接続されたときに呼び出されるメソッドがあります

private void OnClientConnect(IAsyncResult asyncResult)
    {
        try
        {
            //Here we complete/end the Beginaccept() asynchronous call by
            //calling EndAccept() - which returns the reference to a new socket object
            workerSocket[clientCount] = listenSocket.EndAccept(asyncResult);

            //Let the worker socket do the further processing for the just connected client
            WaitForData(workerSocket[clientCount]);

            //Now increment the client count
            ++clientCount;

            if (clientCount<4)//allow max 3 clients
            {
                //Adds the connected client to the list
                connectedClients.Add(listenSocket);
                String str = String.Format("Client # {0} connected", clientCount);                   

                this.Dispatcher.Invoke((Action)(() =>
                {
                    //Display this client connection as a status message on the GUI
                    lbxMessages.Items.Add(str);
                    lblConnectionStatus.Content =clientCount + " Connected";
                }));

                //Since the main Socket is now free, it can go back and wait for
                //other clients who are attempting to connect
                listenSocket.BeginAccept(OnClientConnect, null);
            }
        }
        catch (ObjectDisposedException)
        {
            System.Diagnostics.Debugger.Log(0, "1", "\n OnClientConnection: Socket has been closed\n");
        }
        catch (SocketException)
        {
            HandleClientDisconnect(listenSocket);
        }
    }

(更新) サーバーがクライアントに戻すブロードキャスト メッセージにメソッドを追加

public void broadcast(string msg)
    {
        //foreach (Socket item in connectedClients)
        //{
        Socket broadcastSocket;
        broadcastSocket = workerSocket[0]; //sends message to first client connected
        byte[] broadcastBytes = null;
        broadcastBytes = Encoding.ASCII.GetBytes(msg);
        broadcastSocket.Send(broadcastBytes);
        //}
    }
4

2 に答える 2

0

セルゲイはそれを正しく持っています。1台のサーバーで複数のクライアントを処理する場合は、新しい接続をリッスンできるある種のServerTerminalクラスが必要です。次に、そのソケットへのIOを処理するためのある種の「connectedclient」クラスを設定します。「OnDataReceived」メソッドは、connectedclientクラスにあります。

ソケット受け入れルーチンでは、次のようになります。

private void OnClientConnection(IAsyncResult asyn)
    {
        if (socketClosed)
        {
            return;
        }

        try
        {
            Socket clientSocket = listenSocket.EndAccept(asyn);

            ConnectedClient connectedClient = new ConnectedClient(clientSocket, this, _ServerTerminalReceiveMode);

            connectedClient.StartListening();

受け入れルーチンでは、ソケットが渡されます。これに「clientSocket」という名前を付けました。これは、リスニングソケットではなく、書き込みたいソケットです。

于 2012-12-05T00:21:26.983 に答える
0

サーバー側の TCP 通信には 2 つのソケットが関係しています。最初のソケットはリッスン ソケットであり、新しいリクエストを受け入れるためだけに使用する必要があります。次に、クライアントからの新しいリクエストを受け入れるたびに、接続ごとに別のソケットを取得します。

受け入れたソケット経由ではなく、リッスン ソケット経由でデータを返送しようとしています。

于 2012-12-04T18:56:16.570 に答える