簡體   English   中英

異步客戶端/服務器通信C#

[英]Async Client/Server Communication C#

我正在學習有關客戶端/服務器編程的知識,並且正在制作異步客戶端/服務器聊天應用程序。

我可以將客戶端連接到服務器並發送消息,但是將同一條消息發回客戶端(僅出於測試目的)時遇到問題。 任何幫助表示贊賞...

客戶代碼

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

您應該使用相同的套接字發送和接收數據。 您在socketData.currentSocket上調用EndReceive,因此您也應該調用socketData.currentSocket.Send。

在服務器端有兩個插槽。 一種用於“監聽”,您可以在其上調用接受。 客戶端連接后,accept調用將為該客戶端連接創建一個套接字,然后您可以使用該套接字發送和接收該特定客戶端的數據。

您不使用“偵聽”套接字發送/接收數據。 它沒有連接到特定的連接。 它僅用作接受新客戶端連接的方式。

請參閱http://msdn.microsoft.com/en-us/library/fx6588te.aspx

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM