C#异步客户端无法接收数据

时间:2014-12-10 18:23:42

标签: c# sockets asynchronous client

我使用了codeguru中的代码并对其进行了修改,将必要的异步函数放在类中,以便从主程序中抽象出来。我之所以这样做是因为我们的主程序不仅仅是异步通信;它涉及数据库,但它不是我的项目工作范围。无论如何,来自站点的客户端和服务器的示例代码使用WinForms。在我的实现中,客户端在控制台中(因为它将作为微控制器在Raspberry Pi上运行),而服务器仍在WinForms(PC)中。

我无法让客户端接收数据。尽管说客户端和服务器没有连接但没有错误。

这是处理客户端异步功能的类。

// ClientSocket.cs
namespace Server.Networking
{
    public class ClientSocket
    {
        byte[] _dataBuffer = new byte[10];
        private IAsyncResult _result;
        private AsyncCallback _pfnCallBack;
        public Socket _clientSocket;
        public string ipAddress; // = "192.168.1.101";
        public int port; // = 151;
        public string received = string.Empty;
        public bool hasReceived = false;

        public void ConnectToServer(string ipAddress, int port)
        {
            try
            {
                // Create the socket instance
                _clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                // Create the remote IP address
                IPAddress ip = IPAddress.Parse(ipAddress);

                // Create the end point 
                IPEndPoint ipEnd = new IPEndPoint(ip, port);

                // Connect to the remote host
                _clientSocket.Connect(ipEnd);
                if (_clientSocket.Connected)
                {
                    //Wait for data asynchronously 
                    WaitForData();
                }
            }
            #region catch
            catch (SocketException socketEx)
            {
                Console.WriteLine("Connection failed. Check if the server is running.\n\nError message: {0}", socketEx);
            }
            #endregion
        }

        public void SendMessage(string dataToSend)
        {
            try
            {
                byte[] byData = System.Text.Encoding.ASCII.GetBytes(dataToSend);
                if (_clientSocket != null)
                {
                    _clientSocket.Send(byData);
                }
            }
            #region catch
            catch (SocketException socketEx)
            {
                Console.WriteLine("Connection failed. Check if the server is running.\n\nError message: {0}", socketEx);
            }
            #endregion
        }

        public void WaitForData()
        {
            try
            {
                if (_pfnCallBack == null)
                {
                    _pfnCallBack = new AsyncCallback(OnDataReceived);
                }
                SocketPacket theSocPkt = new SocketPacket();
                theSocPkt.thisSocket = _clientSocket;
                // Start listening to the data asynchronously
                _result = _clientSocket.BeginReceive(theSocPkt.dataBuffer, 0, theSocPkt.dataBuffer.Length, SocketFlags.None, _pfnCallBack, theSocPkt);
            }
            #region catch
            catch (SocketException socketEx)
            {
                Console.WriteLine("Connection failed. Check if the server is running.\n\nError message: {0}", socketEx);
            }
            #endregion
        }

        private void OnDataReceived(IAsyncResult asyn)
        {
            try
            {
                SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
                int iRx = theSockId.thisSocket.EndReceive(asyn);
                char[] chars = new char[iRx + 1];
                System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
                int charLen = d.GetChars(theSockId.dataBuffer, 0, iRx, chars, 0);
                System.String szData = new System.String(chars);
                hasReceived = true;
                received = szData;
                hasReceived = false;
                WaitForData();
            }
            #region catch
            catch (ObjectDisposedException objDispEx)
            {
                Console.WriteLine("Error messsage: {0}", objDispEx);
                System.Diagnostics.Debugger.Log(0, "1", "\nOnDataReceived: Socket has been closed\n");
            }
            catch (SocketException socketEx)
            {
                Console.WriteLine("Connection failed. Check if the server is running.\n\nError message: {0}", socketEx);
            }
            #endregion 
        }

        public void DisconnectFromServer()
        {
            try
            {
                if (_clientSocket != null)
                {
                    _clientSocket.Close();
                    _clientSocket = null;
                }
            }
            #region catch
            catch (Exception stopConEx)
            {
                Console.WriteLine("Error message: {0}", stopConEx);
            }
            #endregion
        }

这是我的主要计划。

namespace Server
{
    public static class Program
    {
        public static ClientSocket _client = new ClientSocket();
        static void Main(string[] args)
        {
            _client.ipAddress = "192.168.1.101";
            _client.port = 151;
            string messageToSend = string.Empty;

            Console.WriteLine("Connecting to server with IP Address {0} at port {1}.", _client.ipAddress, _client.port);

            _client.ConnectToServer(_client.ipAddress, _client.port);

            if (!_client._clientSocket.Connected)
            {
                Console.WriteLine("Cannot connect to server.");
            }
            else
            {
                try
                {
                    while (_client._clientSocket.Connected)
                    {
                        if (_client.hasReceived)
                            Console.WriteLine("Message from server: {0}", _client.received);
                    }
                }
                #region catch
                catch (Exception ex)
                {
                    Console.WriteLine("Error message: {0}", ex);
                }
                #endregion
            }
        }
    }
}

出于简化目的,我让客户端只接收数据,因为我遇到了发送问题。无论如何,这里是我在原始代码中实现的一些修改,当涉及到在客户端接收数据时。

  • 从原始代码(也反映在上面的ClientSocket.cs中),对WaitForData()没有“特殊”调用。通过'特殊'调用,我的意思是线程。运行它,客户端仍然无法接收数据。所以我尝试在类ClientSocket中实现线程,但没有运气。使用Thread.isAlive属性,在调试时,我已经看到线程停止,而我没有明确地在我的代码中说停止线程。当我尝试从服务器发送数据时,它会这样做。即使在我的主程序中进行线程化也行不通。
  • 我添加了变量public bool hasReceivedpublic string received。使用hasReceived,我希望通知代码已在private void OnDataReceived(IAsyncResult asyn)内,并且已收到数据。 received存储收到的数据。到目前为止,hasReceived仅因客户端程序未接收数据而返回false。

有了这些,您能看出为什么我的客户端程序没有接收数据吗?提前谢谢!

0 个答案:

没有答案