Я пытаюсь создать приложение 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();
}
}