Задать вопрос
alex5e
@alex5e

Как правильно получить данные от клиента?

Столкнулся с такой проблемой, что не знаю, как получить ответ от клиента на сервере.
Взял с MSDN пример асинхронного сокет сервера.
собственно сервер:
public class StateObject
    {
        public Socket workSocket = null;
        public const int BufferSize = 1024;
        public byte[] buffer = new byte[BufferSize];
        public StringBuilder sb = new StringBuilder();
    }

    public class AsynchronousSocketListener
    {
        private static String response = String.Empty;
        public static ManualResetEvent allDone = new ManualResetEvent(false);
        private static ManualResetEvent connectDone =
            new ManualResetEvent(false);
        private static ManualResetEvent sendDone =
            new ManualResetEvent(false);
        private static ManualResetEvent receiveDone =
            new ManualResetEvent(false);

        public AsynchronousSocketListener()
        {

        }
        public static void StartListening()
        {
            int countSockets = 0;
            byte[] bytes = new Byte[1024];
            Console.WriteLine(Dns.GetHostName());
            IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
            IPAddress ipAddress = IPAddress.Any;
            IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 5300);
            Socket listener = new Socket(AddressFamily.InterNetwork,
                SocketType.Stream, ProtocolType.Tcp);
                listener.Bind(localEndPoint);
                listener.Listen(100);
                while (true)
                {
                    allDone.Reset();
                    Console.WriteLine("Waiting for a connection...(" + (countSockets + 1) + ")");
                    listener.BeginAccept(
                        new AsyncCallback(AcceptCallback),
                        listener);
                    allDone.WaitOne();
                    countSockets++;
                }
            Console.WriteLine("\nPress ENTER to continue...");
            Console.Read();
        }

        public static void AcceptCallback(IAsyncResult ar)
        {
            allDone.Set();
            Socket listener = (Socket)ar.AsyncState;
            Socket handler = listener.EndAccept(ar);
            StateObject state = new StateObject();
            state.workSocket = handler;
            handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);   
        }

        public static void ReadCallback(IAsyncResult ar)
        {
            String content = String.Empty;
            StateObject state = (StateObject)ar.AsyncState;
            Socket handler = state.workSocket;

            int bytesRead = handler.EndReceive(ar);
            if (bytesRead > 0)
            {
                state.sb.Append(Encoding.ASCII.GetString(
                    state.buffer, 0, bytesRead));
                content = state.sb.ToString();
                if (content.IndexOf("<EOF>") > -1)
                {
                    int[] numbersArray = Program.arrayGenerate(300); 
                    /* Посылаем сериализованный массив */
                    Send(handler, string.Join(",", numbersArray));
                    Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
                        content.Length, content);
                    
                }
                else
                {
                    handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                    new AsyncCallback(ReadCallback), state);
                }
            }
        }

        private static void Send(Socket handler, String data)
        {
            byte[] byteData = Encoding.ASCII.GetBytes(data);
            handler.BeginSend(byteData, 0, byteData.Length, 0,
                new AsyncCallback(SendCallback), handler);
        }
        public static byte[] buffer = new byte[10240];
        private static void SendCallback(IAsyncResult ar)
        {
            try
            {
                Socket handler = (Socket)ar.AsyncState;
                int bytesSent = handler.EndSend(ar);
                Console.WriteLine("Sent {0} bytes to client.", bytesSent);
                handler.Shutdown(SocketShutdown.Both);
                handler.Close();

            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
    }


И клиент:
public class AsynchronousClient
    {
        private const int port = 5300;
        private static ManualResetEvent connectDone =
            new ManualResetEvent(false);
        private static ManualResetEvent sendDone =
            new ManualResetEvent(false);
        private static ManualResetEvent receiveDone =
            new ManualResetEvent(false);

        private static String response = String.Empty;

        public static void StartClient()
        {
            // Connect to a remote device.
            try
            {
                IPHostEntry ipHostInfo = Dns.Resolve("asus");
                IPAddress ipAddress = ipHostInfo.AddressList[0];
                IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
                // Create a TCP/IP socket.
                Socket client = new Socket(AddressFamily.InterNetwork,
                    SocketType.Stream, ProtocolType.Tcp);

                client.BeginConnect(remoteEP,
                    new AsyncCallback(ConnectCallback), client);
                connectDone.WaitOne();

                Send(client, "Client From ip: " + ipAddress  + " connected<EOF>");
                sendDone.WaitOne();
                Receive(client);
                receiveDone.WaitOne();
                // Write the response to the console.
                Console.WriteLine("Received array : ");
                int[] array = Program.toIntArray(response, ',');
                for (int i = 0; i < array.Length; i++) {
                    Console.WriteLine(i + "| " + array[i]);
		}
                int[] arraySort = new int[array.Length];
                Array.Sort(array);
                /* Отдаю обратно массив */
                Send(client, string.Join(",", arraySort));
                sendDone.WaitOne();
                // Release the socket.
                Console.ReadLine();
                client.Shutdown(SocketShutdown.Both);
                client.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        public static void ConnectCallback(IAsyncResult ar)
        {
            try
            {
                Socket client = (Socket)ar.AsyncState;
                client.EndConnect(ar);
                Console.WriteLine("Socket connected to {0}",
                    client.RemoteEndPoint.ToString());
                connectDone.Set();
                
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
        
        private static void Receive(Socket client)
        {
            try
            {
                // Create the state object.
                StateObject state = new StateObject();
                state.workSocket = client;

                // Begin receiving the data from the remote device.
                client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                    new AsyncCallback(ReceiveCallback), state);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        private static void ReceiveCallback(IAsyncResult ar)
        {
            try
            {
                StateObject state = (StateObject)ar.AsyncState;
                Socket client = state.workSocket;
                int bytesRead = client.EndReceive(ar);

                if (bytesRead > 0)
                {
                    // There might be more data, so store the data received so far.
                    state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
                    client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                        new AsyncCallback(ReceiveCallback), state);
                }
                else
                {
                    if (state.sb.Length > 1)
                    {
                        response = state.sb.ToString();
                    }
                    receiveDone.Set();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        private static void Send(Socket client, String data)
        {
            byte[] byteData = Encoding.ASCII.GetBytes(data);
            client.BeginSend(byteData, 0, byteData.Length, 0,
                new AsyncCallback(SendCallback), client);
        }

        private static void SendCallback(IAsyncResult ar)
        {
            try
            {
                // Retrieve the socket from the state object.
                Socket client = (Socket)ar.AsyncState;

                // Complete sending the data to the remote device.
                int bytesSent = client.EndSend(ar);
                Console.WriteLine("Sent {0} bytes to server.", bytesSent);

                // Signal that all bytes have been sent.
                sendDone.Set();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
    }


Я пробовал реализовать на сервере методы Receive и ReceiveCallback как на клиенте но цепляя их к handler я получал exception, т.к. AcceptCallback вызывает BeginReceive(.. ReadCellback), а уже в нем сокет закрывается. А если его не закрыть после отправки, то на клиенте не удается получить данные. В общем, замкнутый круг какой-то. Подскажите пожалуйста, как решить проблему?
  • Вопрос задан
  • 477 просмотров
Подписаться 1 Оценить 1 комментарий
Пригласить эксперта
Ответы на вопрос 2
vpuhoff
@vpuhoff
Программист в свободное от работы время
Нужно больше велосипедов!
Это я к тому, что под 99% существуют готовые реализации, не нужно строить без особой нужды новых велосипедов с квадратными колесами. К примеру одна из таких "нативных" remoting, из коробки решает 95% все вопросов.
Ответ написан
Комментировать
@kttotto
пофиг на чем писать
Это устаревший пример. Этим патерном уже навряд ли пользуются. Есть готовые ассинхронные методы, которые вызываются через async await. Если Вы конечно с нуля пишите свои методы, то в любом случае применяя async await нет необходимости самому писать callback, компилятор все сделает за Вас.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы