0

クライアント/サーバー プログラミングについて学んでおり、非同期クライアント/サーバー チャット アプリケーションを作成しています。

クライアントをサーバーに接続してメッセージを送信できますが、同じメッセージを (テスト目的で) クライアントに送り返すのに問題があります。助けていただければ幸いです...

クライアントコード

byte[] dataBuffer = new byte[10];
    public AsyncCallback callBack;
    public Socket clientSocket;
    IAsyncResult ar;
    Random rnd=new Random();

private void btnSend_Click(object sender, RoutedEventArgs e)
    {
        try
        {
            Object objData = txtMessage.Text;
            byte[] byData = Encoding.ASCII.GetBytes(objData.ToString());
            if (clientSocket != null)
            {
                clientSocket.Send(byData);
                lbxMessages.Items.Add(txtMessage.Text);
            }
            txtMessage.Text = "";
            btnSend.IsEnabled = false;
        }
        catch(SocketException se)
        {
            MessageBox.Show(se.Message);
        }
    }

//SocketPacket CLASS
    public class SocketPacket
    {
        public Socket thisSocket;
        public byte[] dataBuffer = new byte[10];//test no, prevous [1]
    }

//METHODS
    private void WaitForData()
    {
        try
        {
            if (callBack == null)
            {
                callBack = new AsyncCallback(OnDataReceived);
            }
            SocketPacket sckPack = new SocketPacket();
            sckPack.thisSocket = clientSocket;
            ar = clientSocket.BeginReceive(sckPack.dataBuffer, 0, sckPack.dataBuffer.Length, SocketFlags.None, callBack, sckPack);

        }
        catch(SocketException se)
        {
            MessageBox.Show(se.Message);
        }
    }

    public void OnDataReceived(IAsyncResult ar)
    {
        try
        {
            SocketPacket sckID = (SocketPacket)ar.AsyncState;
            int iRx = sckID.thisSocket.EndReceive(ar);
            char[] chars = new char[iRx + 1];
            Decoder d = Encoding.UTF8.GetDecoder();
            int charLen = d.GetChars(sckID.dataBuffer, 0, iRx, chars, 0);
            String szData = new String(chars);
            this.Dispatcher.Invoke((Action)(() =>
            {
                lbxMessages.Items.Add(txtMessage.Text + szData);
            }));
            WaitForData();
        }
        catch (ObjectDisposedException)
        {
            Debugger.Log(0, "1", "\n OnDataRecieved: Socket has been closed\n");
        }
        catch(SocketException se)
        {
            MessageBox.Show(se.Message);
        }
    }

サーバーコード

private void OnClientConnect(IAsyncResult asyncResult)
    {
        try
        {
            workerSocket[clientCount] = listenSocket.EndAccept(asyncResult);
            WaitForData(workerSocket[clientCount]);
            ++clientCount;

            if (clientCount<4)//allow max 3 clients
            {

                String str = String.Format("Client # {0} connected", clientCount);                   

                this.Dispatcher.Invoke((Action)(() =>
                {
                    lbxMessages.Items.Add(str);
                    lblConnectionStatus.Content =clientCount + " Connected";
                }));

                listenSocket.BeginAccept(OnClientConnect, null);
            }
        }
        catch (ObjectDisposedException)
        {
            System.Diagnostics.Debugger.Log(0, "1", "\n OnClientConnection: 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);
        }
    }

    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);

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

            //Does not work - does not send same message back to client
            //byte[] byData = Encoding.ASCII.GetBytes(receivedData);
            //if (listenSocket != null)
            //{
            //    listenSocket.Send(byData);
            //}

            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);
        }
    }
4

1 に答える 1

0

データの送受信には同じソケットを使用する必要があります。socketData.currentSocket で EndReceive を呼び出すので、socketData.currentSocket.Send も呼び出す必要があります。

サーバー側には 2 つのソケットがあります。1つは「リスニング」に使用され、acceptを呼び出します。クライアントが接続すると、accept 呼び出しによってそのクライアント接続専用のソケットが作成されます。これを使用して、その特定のクライアントのデータを送受信します。

データの送受信に「リスニング」ソケットを使用しません。特定の接続に接続されていません。これは、新しいクライアント接続を受け入れる方法としてのみ機能します。

http://msdn.microsoft.com/en-us/library/fx6588te.aspxを参照してください。

于 2013-04-13T07:49:45.330 に答える