C# сокет постоянно обменивается сообщениями

Я несколько дней борюсь с этой проблемой. У меня есть сервер, и мне нужно реализовать клиент. Сначала я отправляю сообщение для входа и получаю ответ. После этого мне нужно будет отправлять и получать разные сообщения. От 10 до 10 секунд мне нужно отправить "сообщение сердцебиения", поэтому сервер должен знать, что соединение все еще активно. Я сделал это простым асинхронным клиентом.

 private static void Send(Socket client, String data)
    {

      byte[] byteData = charTobyte(data.ToCharArray());
      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);
                sendDone.Set();

            }
            catch (Exception e)
            {
                Console.WriteLine(e.StackTrace + " " + e.Message);
            }
        }


     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
            {
                // Retrieve the state object and the client socket   
                // from the asynchronous state object.  
                StateObject state = (StateObject)ar.AsyncState;
                Socket client = state.workSocket;


                // Read data from the remote device.  
                int bytesRead = client.EndReceive(ar);

                if (bytesRead > 0)
                {

                    state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));


                    client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                        new AsyncCallback(ReceiveCallback), state);
                }
                else
                {
                    // All the data has arrived; put it in response.  
                    if (state.sb.Length > 1)
                    {
                       response = state.sb.ToString();
                        Console.WriteLine("Response: " + response);
                    }
                    receiveDone.Set();

                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.StackTrace + " " + e.Message);
            }
        }


 private static void Heartbeat(object source, System.Timers.ElapsedEventArgs e, Socket client)
        {

            try
            {
                Console.WriteLine("Heartbeat...sent");
                SendHeart(client, DPLHeader(HeartBeat));
                sendHeart.WaitOne();

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.StackTrace + " " + ex.Message);
            }
            finally
            {
                Console.WriteLine("value: " + client.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive) + " : " + client.Connected);

            }

        }

Вот что я делаю в StartClient():

public static void StartClient()
        {
            // Connect to a remote device.  
            try
            {


                client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);


                // Connect to the remote endpoint.  
                client.BeginConnect(remoteEP,
                    new AsyncCallback(ConnectCallback), client);
                connectDone.WaitOne();

                timer.Interval = 10000;
                timer.Elapsed += new System.Timers.ElapsedEventHandler((source, e) => Heartbeat(source, e, client));
                timer.Enabled = false;
                timer.AutoReset = false;

                timer.Start();

                message = DPLHeader(Messages.ElementAt(j));

                Send(client, message);
                sendDone.WaitOne();

                Console.WriteLine("value: " + client.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive) + " : " + client.Connected);



            }
            catch (Exception e)
            {
                Console.WriteLine(e.StackTrace + " " + e.Message);
            }
        }

SendHeart() так же, как обычный Send, просто отправляет сообщение keepalive.

Проблема, с которой я сталкиваюсь, заключается в следующем: после первого использования таймера и запуска Heartbeat() приложение отправляет только сообщение keepallive, поэтому другие сообщения не отправляются. Если он отправляет только сообщение keepallive, соединение поддерживается живым. Подобно тому, как клиент больше не может получить доступ к обратному вызову Send, он остается только для Heartbeat.

В другом случае я сделал 3 таймера, один для Send(), один для Receive() и один для Heartbeat(). В этом порядке и когда один таймер истекает, он останавливается и запускает следующий, и так далее. Я отправляю сообщение, читаю ответ и отправляю Heartbeat, после чего при любом движении я пытаюсь сделать BeginSend сообщение или BeginReceive сообщение, соединение на хост-компьютере прерывается.

Во втором случае другой проблемой будет то, что если после отправки сообщения и запускается Прием, если отправляется Heartbeat, поток приема теряется, поэтому я больше не могу читать сообщение.

Извините, если это слишком запутано. Я жду вопросов, если вы что-то не поняли. Спасибо

0 ответов

Другие вопросы по тегам