Клиент сокета asyn c после подключения к стороннему программному обеспечению продолжает прослушивать входящие сообщения - PullRequest
0 голосов
/ 05 марта 2020

Я пытаюсь создать приложение WPF, которое однажды отправило сообщение через TCP стороннему приложению, прослушало ответ и продолжило прослушивать входящее сообщение (Это стороннее приложение отправляет отзыв последнему подключенному или проверенный контроллер), пока не будет отправлено другое сообщение и т. д.

Это должен быть асинхронный c, потому что мое приложение должно работать непрерывно, чтобы выполнять другие действия.
В основном я адаптировал этот (https://docs.microsoft.com/it-it/dotnet/framework/network-programming/asynchronous-client-socket-example) пример к WPF используя backgoundWorker и никогда не закрывая сокет.

Кажется, проблема в том, что

client.BeginReceive(state.buffer, 0, state.buffer.Length, 0, new asyncCallback(ReceiveCallback), state);

Не будет зацикливаться, если последние прочитанные байты меньше размера буфера.

мой код:

using System;
using System.ComponentModel;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows;

namespace socket_WPF
{
    /// <summary>
    /// Logica di interazione per MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private readonly BackgroundWorker BWI;
        public AsyncSocketReceiver ASR;
        public string risposta = "";
        public string rispostaOLD;
        public bool newMessage = false;
        public string Extmessage;
        public int Mcounter = 0;
        public MainWindow()
        {
            InitializeComponent();
            BWI = new BackgroundWorker
            {
                WorkerReportsProgress = true,
                WorkerSupportsCancellation = true
            };
            BWI.DoWork += new DoWorkEventHandler(BWI_DoWork);
            BWI.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BWI_RunWorkerCompleted);
            BWI.ProgressChanged += new ProgressChangedEventHandler(BWI_ProgressChangedEventHandler);
        }

        private void BWI_DoWork(object sender, DoWorkEventArgs e)
        {
            int i = -1;
            BackgroundWorker myBW = sender as BackgroundWorker;
            ASR = new AsyncSocketReceiver("192.168.1.106", 3040);
            ASR.Connect();
            ASR.Send(string.Format("[{0}] ping \r", Mcounter));
            ASR.sendDone.WaitOne();
            newMessage = false;
            while (AsyncSocketReceiver.client.Connected)
            {
                if (newMessage)
                {
                    var toSend = string.Format("[{0}] " + Extmessage + "\r", Mcounter++);
                    ASR.Send(toSend);
                    ASR.sendDone.WaitOne();
                    newMessage = false;
                }
                ASR.Receive();
                ASR.receiveDone.WaitOne();
                risposta = ASR.response;

                myBW.ReportProgress(i++);
            }
        }

        private void BWI_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            BWI.RunWorkerAsync();
        }

        private void BWI_ProgressChangedEventHandler(object sender, ProgressChangedEventArgs e)
        {
            CueAnswer.Document.Blocks.Clear();
            CueAnswer.AppendText(risposta);
        }

        private void AsyncSocket_Click(object sender, RoutedEventArgs e) => BWI.RunWorkerAsync();

        private void AskC_Click(object sender, RoutedEventArgs e)
        {
            ASR.receiveDone.Set();
            Extmessage = MessageToSend.Text;
            newMessage = true;
        }
    }

    public class AsyncSocketReceiver
    {
        private static IPEndPoint remoteEP;
        public static Socket client;
        public ManualResetEvent connectDone = new ManualResetEvent(false);
        public ManualResetEvent sendDone = new ManualResetEvent(false);
        public ManualResetEvent receiveDone = new ManualResetEvent(false);
        public String response;
        public String query;

        public AsyncSocketReceiver(String myIp, int myPort)
        {
            remoteEP = new IPEndPoint(IPAddress.Parse(myIp), myPort);
            client = new Socket(IPAddress.Parse(myIp).AddressFamily,
                SocketType.Stream, ProtocolType.Tcp)
            {
                Blocking = false
            };
        }

        public void Connect()
        {
            client.BeginConnect(remoteEP,
                new AsyncCallback(ConnectCallback), client);
            connectDone.WaitOne();
        }

        private void ConnectCallback(IAsyncResult ar)
        {
            try
            {
                Socket client = (Socket)ar.AsyncState;
                client.EndConnect(ar);
                connectDone.Set();
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
            }
        }

        public void Send(String data)
        {
            query = data;
            response = "";
            byte[] byteData = Encoding.ASCII.GetBytes(data);
            client.BeginSend(byteData, 0, byteData.Length, 0,
                new AsyncCallback(SendCallback), client);
        }

        private void SendCallback(IAsyncResult ar)
        {
            try
            {
                Socket client = (Socket)ar.AsyncState;
                int bytesSent = client.EndSend(ar);
                sendDone.Set();
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
            }
        }

        public void Receive()
        {
            try
            {
                StateObject state = new StateObject
                {
                    workSocket = client
                };
                receiveDone.Reset();
                client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                    new AsyncCallback(ReceiveCallback), state);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
            }
        }

        private void ReceiveCallback(IAsyncResult ar)
        {
            try
            {
                StateObject state = (StateObject)ar.AsyncState;
                int bytesRead = client.EndReceive(ar);
                if (bytesRead > 0)
                {
                    state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
                    client.BeginReceive(state.buffer, 0, state.buffer.Length, 0,
                                 new AsyncCallback(ReceiveCallback), state);
                }
                else
                {
                    response = state.sb.ToString();
                    receiveDone.Set();
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
            }
        }
    }
    public class StateObject
    {
        public Socket workSocket = null;
        public const int BufferSize = 256;
        public byte[] buffer = new byte[BufferSize];
        public StringBuilder sb = new StringBuilder();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...