Клиент и сервер С# UDP, я не понимаю использование асинхронности и связи между двумя сценариямиC#

Место общения программистов C#
Ответить
Anonymous
 Клиент и сервер С# UDP, я не понимаю использование асинхронности и связи между двумя сценариями

Сообщение Anonymous »

Я никогда раньше не пробовал UDP. Синхронная версия работает, но мне нужна асинхронная.
Клиент должен подключиться к фабрике, отправить как парольную фразу, сервер тоже ее сравнивает. После этого сервер должен отправить датапак (удаленный сброс). После этого все должно закрыться. Сервер по-прежнему должен принимать другие запросы на подключение.
Я попробовал список задач, но не смог заставить его работать. Я даже не могу заставить асинхронную работу работать. Есть какие-нибудь советы?
Этот скрипт — мой новейший клиентский скрипт:

Код: Выделить всё

class UDPClient : IDisposable
{
public static bool messageReceived = false;

public const int listenPort = 11000;

public byte[] firstMessage = Encoding.ASCII.GetBytes("I heard you");
public byte[] firstCond = Encoding.ASCII.GetBytes("Send Login Data");

public AsyncCallback checkConnectionCB = new AsyncCallback(CheckConnection);

public struct UdpState
{
public UdpClient listenerMaster;   //u
public IPEndPoint customerMaster;       // e
}

static void Main()
{
UDPClient start = new UDPClient();
start.StartListener();
}

public void Dispose()
{
throw new NotImplementedException();
}

// Send message to customer here (eg Login)
// send data package if ok
public void StartListener()
{
UdpClient listener = new UdpClient();
IPEndPoint customer = new IPEndPoint(IPAddress.Any, listenPort);

listener.Connect(customer);
listener.DontFragment = true;

Console.WriteLine("Connecting to factory (StartListener)");

// Wait for customer ip and port
// save customer ip and port so listener can open new line
listener.Connect(customer);

Console.WriteLine("Connecting to customer");

try
{
listener.BeginSend(firstMessage, firstMessage.Length, checkConnectionCB, firstCond);
}
catch (SocketException e)
{
Console.WriteLine(e);
}
}

public static void CheckConnection(IAsyncResult resultConnection)
{
Console.WriteLine("CheckConnection IAsyncREsult sollte kommen");
}
}
Я попробовал список задач, но там не было соединения. Я просто не могу понять, как это должно работать и как заставить это работать...
РЕДАКТИРОВАТЬ:
изменил мой код (серверная/заводская сторона), остались вопросы
Сейчас попробовал заводскую сторону. Он должен прослушивать любой IP позже. Теперь у меня нет точки входа, кроме использования static async void Main().
Я почувствовал, что есть серьезные ошибки, но каким-то образом мне удалось это сделать: Visual Studio не выдает много ошибок.Мои вопросы:
  • Как мне сказать, что метод Main() является отправной точкой? Каким-то образом это сработало с моим старым кодом...
  • Как мне запустить его, когда кто-то с ним связывается и где мне открыть еще один прослушиватель чтобы он мог получить еще один запрос во время работы над первым?
  • Открывает ли он разные прослушиватели или для списка задач он всегда один и тот же? ?

    Код: Выделить всё

      using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net.Sockets;
    using System.Net;
    using System.Text;
    using System.Threading.Tasks;
    using System.Net.NetworkInformation;
    using System.Runtime.CompilerServices;
    using System.Security.Cryptography.X509Certificates;
    
    namespace Factory
    {
    // CHANGE: Customer IP to Any IP
    // CHANGE: customer Port to Any Port
    class FactoryUDP : UdpClient, IDisposable
    {
    public bool IsCompleted { get; }
    
    public const int listenPort = 11000;
    
    public static bool isConnected;
    public static bool messageReceived;
    
    public string testData = "UserName PassWord";
    
    public byte[] message1 = Encoding.ASCII.GetBytes("Please write user name and password, separated with one space and hit enter.");
    public object? sendOne;
    
    public IAsyncResult? loginAsyncResult;
    
    static async void Main()
    {
    Console.WriteLine("Starting Main");
    
    FactoryUDP start = new FactoryUDP();
    start.RemoteReset();
    // await/ return / something;
    }
    
    public struct UdpState
    {
    public UdpClient u;     //listener
    public IPEndPoint e;    //customer
    }
    
    /*
    public void Dispose()
    {
    throw new NotImplementedException();
    }
    */
    
    public async Task RemoteReset()
    {
    
    var connectionTask = ConnectCustomer();
    var loginTask = LoginRequest();
    var sendRemoteTask = SendRemoteReset();
    var closeTask = CloseEverything();
    
    await connectionTask;
    await loginTask;
    await sendRemoteTask;
    
    var remoteTasks = new List { connectionTask, loginTask, sendRemoteTask };
    while (remoteTasks.Count > 0)
    {
    Task finishedTask = await Task.WhenAny(remoteTasks);
    if (finishedTask == connectionTask)
    {
    Console.WriteLine("ConnectionTask finished");
    }
    else if (finishedTask == loginTask)
    {
    Console.WriteLine("LoginTask finished");
    }
    else if (finishedTask == sendRemoteTask)
    {
    Console.WriteLine("Send remote Task finished");
    }
    await finishedTask;
    
    Console.WriteLine($"Task isCompleted state: {IsCompleted}");
    await Task.WhenAll(remoteTasks.ToArray());
    // remoteTasks.Remove(finishedTask);
    // Task list: wait for all remoteTasks and then CloseEverything();
    }
    
    async Task ConnectCustomer()
    {
    UdpClient u = new UdpClient(listenPort);
    IPEndPoint e = new IPEndPoint(IPAddress.Any, listenPort);
    
    u.Connect(e);
    u.DontFragment = true;
    
    isConnected = true;
    
    u.BeginReceive(ReceiveCallback1, e);        // EndReceive in ReceiveCallback1
    Console.WriteLine("BeginReceive - ReceiveCallback1 in ConnectCustomer");
    
    u.BeginSend(message1, message1.Length, SendCallback1, sendOne);  // EndSend in SendCallback1
    Console.WriteLine("BeginSend Message1 - SendCallback1 in ConnectCustomer");
    
    // when connected to customer add a new listener to listen for other customers?
    
    await ConnectCustomer();
    await LoginRequest();
    //await LoginCompare();
    await SendRemoteReset();
    
    }
    
    async Task LoginRequest()
    {
    // begin receive, user name and password separated with space?
    
    UdpClient u = ((UdpState)loginAsyncResult.AsyncState).u;
    IPEndPoint e = ((UdpState)loginAsyncResult.AsyncState).e;
    
    UdpState s = new UdpState();
    s.e = e;
    s.u = u;
    
    u.BeginReceive(new AsyncCallback (ReceiveCallback2), s);
    byte[] receiveLoginData = u.EndReceive(loginAsyncResult, ref e);
    string receiveLoginDataString = Encoding.ASCII.GetString(receiveLoginData);
    Console.WriteLine($"Received Login data: {receiveLoginDataString}");
    
    // separate string to user name (space) password        receiveLoginDataString
    //What to do with the login data? write in j son?
    
    if (testData == receiveLoginDataString)
    {
    await SendRemoteReset();
    Console.WriteLine("Successfully compared testData with receivedString, awaiting SendRemoteReset");
    }
    else
    {
    await CloseEverything();
    Console.WriteLine("Failed to compare testData with received LoginData. Awaiting CloseEverything");
    }
    
    //return Task.;
    await LoginRequest();
    }
    
    static async Task SendRemoteReset()
    {
    Console.WriteLine("SendRemoteReset here (datapack)");
    //send remote reset data pack and CloseEverything()
    await Task.Delay(2);
    }
    
    static async Task CloseEverything()
    {
    isConnected = false;
    
    Console.WriteLine("CloseEverything here.  Waiting for Task.Delay(330)");
    
    await Task.Delay(300);
    // Close everything and start another listener for customers
    }
    
    static async void ReceiveCallback1(IAsyncResult ar1)
    {
    UdpClient u = ((UdpState)ar1.AsyncState).u;
    IPEndPoint e = ((UdpState)ar1.AsyncState).e;
    
    byte[] receiveBytes = u.EndReceive(ar1, ref e);
    string receiveString = Encoding.ASCII.GetString(receiveBytes);
    
    Console.WriteLine($"Received: {receiveString}");
    messageReceived = true;
    Console.WriteLine("Setting messageReceived to true");
    
    return;
    }
    // public delegate here?
    
    async void SendCallback1(IAsyncResult? sendOne)
    {
    UdpClient u = ((UdpState)sendOne.AsyncState).u;
    IPEndPoint e = ((UdpState)sendOne.AsyncState).e;
    
    u.EndSend(sendOne);
    Console.WriteLine("EndSend ind SendCallback1 here");
    
    await LoginRequest();
    }
    
    async void ReceiveCallback2(IAsyncResult? loginAsyncResult)
    {
    UdpClient u = ((UdpState)loginAsyncResult.AsyncState).u;
    IPEndPoint e = ((UdpState)loginAsyncResult.AsyncState).e;
    
    byte[] receiveLoginData = u.EndReceive(loginAsyncResult, ref e);
    string receiveLoginDataString = Encoding.ASCII.GetString(receiveLoginData);
    Console.WriteLine($"Received Login data: {receiveLoginDataString}");
    
    return;
    
    // go to LoginRequest from here?
    }
    
    }
    
    }
    
    }
редактировать 11 июля 2024 г.
Я переписал снова написал код, снова многому научился, но все еще не могу заставить сервер и клиент взаимодействовать друг с другом...
сторона сервера:

Код: Выделить всё

    class FactoryUDP : UdpClient, IDisposable
{
// https://stackoverflow.com/questions/7266101/receive-messages-continuously-using-udpclient
public bool IsCompleted { get; }

public byte[] factoryIP = new byte[] { 127, 0, 0, 1 }; // line 83/84                    //ToDo.MG rewrite for any IP and remove
public const int listenPort = 11000;                                    //ToDo.MG rewrite for any IP and remove

public static bool isConnected;
public static bool messageReceived;

public string testData = "UserName PassWord";                           //ToDo.MG rewrite and remove
public string? receiveLoginDataString;

public byte[] message1 = Encoding.ASCII.GetBytes("Please write user name and password, separated with one space and hit enter.");   //ToDo.MG rewrite and remove

public object? sendOne;
public object? loginAsyncResult;
public object? cusConnSuccess;

//private static bool IsNotNull1([NotNullWhen(true)] object? cusConnSucc) => cusConnSucc != null;
//private static bool IsNotNull2([NotNullWhen(true)] object? sendOne) => sendOne != null;

static void Main()
{
FactoryUDP start = new FactoryUDP();
start.MainAsync().Wait();
}
public async Task MainAsync()
{
UdpClient uMaster = new UdpClient(listenPort);
IPEndPoint eMaster = new IPEndPoint(new IPAddress(factoryIP), listenPort);

var connectionTask = ConnectCustomer();
var loginTask = LoginRequest();
var sendRemoteTask = SendRemoteReset();
var closeTask = CloseEverything();

await connectionTask;
await loginTask;
await sendRemoteTask;
await closeTask;

var remoteTasks = new List { connectionTask, loginTask, sendRemoteTask, closeTask };
while (remoteTasks.Count >  0)
{
Console.WriteLine("Task List here");
Task finishedTask = await Task.WhenAny(remoteTasks);
if (finishedTask == connectionTask)
{
Console.WriteLine("ConnectionTask finished");
}
else if (finishedTask == loginTask)
{
Console.WriteLine("LoginTask finished");
}
else if (finishedTask == sendRemoteTask)
{
Console.WriteLine("Send remote Task finished");
}
else if (finishedTask == closeTask)
{
Console.WriteLine("Send close Task finished");
}
await finishedTask;

Console.WriteLine($"Task isCompleted state: {IsCompleted}");
await Task.WhenAll();
}

async void ReceiveCallback1(IAsyncResult cusConnSucc)
{
Console.WriteLine("BeginReceive - ReceiveCallback1 in ConnectCustomer");
isConnected = true;

byte[] receiveBytes = uMaster.EndReceive(cusConnSucc, ref eMaster);
string receiveString = Encoding.ASCII.GetString(receiveBytes);
Console.WriteLine($"Received in ReceiveCallback1: {receiveString}");

bool connectMessage = receiveBytes.Equals(Encoding.ASCII.GetBytes("Factory! Listen!"));
Console.WriteLine($"Received bytes from Gripper: {connectMessage}");

if (connectMessage == true &&  isConnected)
{
messageReceived = true;
Console.WriteLine("Setting messageReceived to true (only if isConnected is also true).");
// AsyncCallback callbackCustomerConnect = new AsyncCallback(LoginRequest);
}
else
{
Console.WriteLine("Something went wrong with compare connectMessage");
await CloseEverything();
}
cusConnSucc.AsyncWaitHandle.WaitOne();
}

async void SendCallback1(IAsyncResult sendOne)
{
Console.WriteLine("BeginSend Message1 - SendCallback1 in ConnectCustomer");

uMaster.EndSend(sendOne);
Console.WriteLine("EndSend in SendCallback1 here");

sendOne.AsyncWaitHandle.WaitOne();
}

async void ReceiveCallback2(IAsyncResult? loginAsyncResult)
{
Console.WriteLine("BeginReceive - Callback 2 in LoginRequest");

byte[] receiveLoginData = uMaster.EndReceive(loginAsyncResult, ref eMaster);
string receiveLoginDataString = Encoding.ASCII.GetString(receiveLoginData);

Console.WriteLine($"Received Login data: {receiveLoginDataString}");

loginAsyncResult.AsyncWaitHandle.WaitOne();
}

async Task ConnectCustomer()
{
uMaster.Connect(eMaster);

Console.WriteLine("Task ConnectCustomer BeginReceive, BeginSend, BeginReceive which are just laying here");
uMaster.BeginReceive(ReceiveCallback1, cusConnSuccess);

uMaster.BeginSend(message1, message1.Length, SendCallback1, sendOne);

uMaster.BeginReceive(ReceiveCallback2, loginAsyncResult);

await ConnectCustomer();
}

async Task LoginRequest()
{
bool login = receiveLoginDataString.Equals(testData);
if (login == true)
{
Console.WriteLine("login = true, next is SendRemoteReset");
await SendRemoteReset();
}
else
{
Console.WriteLine("LoginRequest, login false");
await CloseEverything();
}
}

async Task SendRemoteReset()
{
Console.WriteLine("SendRemoteReset here (data pack), now TaskDelay(300) in SendRemoteTask");
await Task.Delay(300);
}

async Task CloseEverything()
{
isConnected = false;
Console.WriteLine("CloseEverything here.  Waiting for Task.Delay(600)");
await Task.Delay(600);
Console.WriteLine("Closing Everything last line.");
Console.WriteLine("Continue with any Key here, so the program stops for a moment");
Console.ReadKey(); // just so it won't repeat all the time
}
}
}
и клиент

Код: Выделить всё

    class GripperUDP : UdpClient, IDisposable
{
public bool IsCompleted { get; }

public static bool isConnected;

object sendFirst;
object receiveOne;
object logDataState;

public const int listenPort = 11001;
public byte[] factoryIP = new byte[] { 127, 0, 0, 1 };

public string compareLoginData = "UserName PassWord";

public byte[] connectMessage = Encoding.ASCII.GetBytes("Factory! Listen!");

static void Main()
{
GripperUDP start = new GripperUDP();
start.MainAsync().Wait();
}

public async Task MainAsync()
{
UdpClient uMaster = new UdpClient(listenPort);
IPEndPoint eMaster = new IPEndPoint(new IPAddress(factoryIP), listenPort);

var connectionTask = ConnectFactory();
var receiveRemoteTask = ReceiveRemoteReset();
var closeTask = CloseEverything();

await connectionTask;
await receiveRemoteTask;

var remoteTasks = new List { connectionTask, receiveRemoteTask, closeTask };
while (remoteTasks.Count > 0)
{
Task finishedTask = await Task.WhenAny(remoteTasks);
if (finishedTask == connectionTask)
{
Console.WriteLine("ConnectionTask finished");
}
else if (finishedTask == receiveRemoteTask)
{
Console.WriteLine("Receive remote Task finished");
}
else if (finishedTask == closeTask)
{
Console.WriteLine("Close Task finished");
}
await finishedTask;
Console.WriteLine($"Task isCompleted state: {IsCompleted}");

await Task.WhenAll(remoteTasks.ToArray());
// remoteTasks.Remove(finishedTask);
}

async void SendCallback1(IAsyncResult? sendFirstObject)
{
if (sendFirstObject != null)
{
uMaster.EndSend(sendFirstObject);
Console.WriteLine("EndSend in SendCallback1 here");

sendFirstObject.AsyncWaitHandle.WaitOne();
}
else
{
Console.WriteLine("sendFirst is null exception. Closing with uMaster.Close.");
uMaster.Close();
}
}

async void ReceiveCallback1(IAsyncResult received)
{
if (received != null)
{
byte[] receivedBytes = uMaster.EndReceive(received, ref eMaster!);
string receivedString = Encoding.ASCII.GetString(receivedBytes);

bool receivedMessageFactory = receivedBytes.Equals(Encoding.ASCII.GetBytes("Please write user name and password, separated with one space and hit enter."));
Console.WriteLine($"Received: {receivedString}");

if (receivedMessageFactory == true)
{
Console.WriteLine("received loginRequestMessage from factory. forwarding to LoginRequest");

uMaster.BeginReceive(ReceiveCallback2, logDataState);
Console.WriteLine("Begin ReceiveCallBack 2");

received.AsyncWaitHandle.WaitOne();
}
else
{
Console.WriteLine("Wrong factory message received.  now uMaster.Close();");
uMaster.Close();
}
}
}

async void ReceiveCallback2(IAsyncResult callBack2Object)
{
if (callBack2Object != null)
{

byte[] receivedLoginData = uMaster.EndReceive(callBack2Object, ref eMaster!);
string loginInfo = receivedLoginData.ToString();
Console.WriteLine("receivedLoginData converted to String, comparing next");

bool loginCheck = loginInfo.Equals(compareLoginData);

if (receivedLoginData != null)
{
if (loginCheck == true)
{
Console.WriteLine("LoginCheck successful");
callBack2Object.AsyncWaitHandle.WaitOne();
await ReceiveRemoteReset();
}
else
{
Console.WriteLine("Login Check/compare went wrong. Now uMaster.Close();");
uMaster.Close();
}
}
else
{
Console.WriteLine("Something went wrong in LoginRequest / comparing. Closing with uMaster.Clsoe()");
uMaster.Close();
}
callBack2Object.AsyncWaitHandle.WaitOne();
}
}

async Task ConnectFactory()
{
uMaster.Connect(eMaster);

isConnected = true;

uMaster.BeginReceive(ReceiveCallback1, receiveOne);
Console.WriteLine("First beginReceive");

uMaster.BeginSend(connectMessage, connectMessage.Length, SendCallback1, sendFirst);
Console.WriteLine("First beginSend");

await ReceiveRemoteReset();
}

static async Task CloseEverything()
{
isConnected = false;

Console.WriteLine("CloseEverything here. Waiting for Task.Delay(200) in same method");
await Task.Delay(200);

Console.WriteLine("Closing Everything after Delay (ReadKey) for waiting");
Console.ReadLine();
}

static async Task ReceiveRemoteReset()
{
if (isConnected == true)
{
Console.WriteLine("Waiting Task Delay (600) of ReceiveRemoteReset.)");
await Task.Delay(600);
Console.WriteLine("Task.Dealy(600) over. CloseEverything()");
await CloseEverything();
}
else
{
Console.WriteLine("ReceiveRemoteReset, isConnected false CloseEverything()");
await CloseEverything();
}
}

}
}
на данный момент установите фиксированный IP-адрес, но позже сервер должен будет прослушивать любой IP-адрес. Есть какие-нибудь советы о том, что все еще не так? (постоянно исправлено создание новых клиентов udp). клиент прослушает свое сообщение и т. д.

Подробнее здесь: https://stackoverflow.com/questions/787 ... munication
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»