"DLL'leri Kullanmadan Adlandırılmış Kanalları Kullanarak MetaTrader 5 ile İletişim Kurma" makalesi için tartışma - sayfa 3

 
Renat:
Terminaller arasındaki iletişim konusunun küçük bir uygulama oranına sahip olduğunu düşünüyorum.

Ancak dış sistemlerle iletişim daha önemli ve uygulanabilir. Güvenli kanal bunun için açıldı.

Kimse buna itiraz etmiyor, yani her şeyin ne için yapıldığının beyan edilmesine. Ancak sorun bunun nasıl uygulandığıdır. Sonuçta harici sistemler illa ki C dilinde yazılmak zorunda değil, farklı programlama dillerinde de oluşturulabilir. Ve birçok programlama dilinde adlandırılmış bir kanal aracılığıyla terminale sadece dosya işlemleri aracılığıyla bir istemci olarak bağlanmak mümkündür. Ancak teknoloji istemci-sunucu olarak seçildi, yani iki istemci arasında bir köprü - ağ geçidi olmadan bir boşluk varsa birbirleriyle karşılaşmayacak şekilde. Yani ya istemci-istemci teknolojisi ya da bir ağ geçidi sağlanmalıydı. Ve böylece büyükbaba Krylov'un "Tilki ve Üzüm" masalındaki gibi oldu:

Göz görse de,

Ama göz göremez.

© I. Krylov


Diğerlerinin dış sistemlerle benzer bir bağlantıyı nasıl gerçekleştirdiklerine bakmak gerekiyordu. Örneğin: VMWare, MS SQL Server, MySQL, harici modemler vb. Sunucu kısımları dahili olarak uygulanmaktadır. Ve herhangi bir koltuk değneği olmadan, adlandırılmış bir kanal veya TCP/IP ve diğer iletişim kanalları aracılığıyla bile katılmak çok uygundur. Ve hatta, örneğin, adlandırılmış bir kanal aracılığıyla, ancak "Named Pipe TCP Proxy" yardımcı programının yardımıyla TCP / IP üzerinden uzaktan seçim yapabilirsiniz. Yani, kullanıcıların herhangi bir ek koltuk değneği oluşturmasına gerek yoktur, ancak yalnızca en uygun istemci uygulamasını seçer ve hemen bağlanır ve çalışır.
 
Yuri, açıkça kafan karışmış. Sunucu boru hatları diğer dillerde kolayca oluşturulabilir. Bu sadece WinAPI.

MQL5'in güvenli bir uygulama ortamı olduğunu ve açıkça sunucu işlevleri oluşturmanın mantıksız olduğu bir istemci ortamı olduğunu göz önünde bulundurun.

Sunucu işlevselliğinin beyan edildiğinden emin değilim. İstemci işlevselliği planlandı ve uygulandı.
 

Sanırım ağ geçidi için kodu hazırladım. Henüz test etmedim. MinGW'yi indirip kuracağım ve neyin yanlış olduğunu göreceğim.

#using <System.Core.dll>

using namespace System;
using namespace System::IO;
using namespace System::IO::Pipes;
using namespace System::Text;
using namespace System::Threading;


public ref class PipeServer
{
private:
       NamedPipeServerStream^ pipeServer1;
       NamedPipeServerStream^ pipeServer2;
    

public:
    static void Main()
    {
        int i;
        Thread server;

        Console::WriteLine("\n*** Named pipe server stream with impersonation example ***\n");
        Console::WriteLine("Waiting for client connect...\n");
        // Adlandırılmış kanallardan bilgi kopyalamak için ilk alt süreci oluşturun
        Thread server = gcnew Thread(gcnew ThreadStart(&ServerThread));
        // Çalıştır
        server->Start();
        Thread::Sleep(250);
        // İstemci çökmüşse
        if (servers != nullptr)
        {
          if (server->Join(250))
                                        {
            Console::WriteLine("Server finished.", server->ManagedThreadId);
            servers = nullptr;
          }
        }
        Console::WriteLine("\nServer threads exhausted, exiting.");
    }

private:
    static void ServerThread()
    {
        int threadId;
        bool needclose = false;
        if (i == 0) 
        {
            // İki adlandırılmış kanal oluşturun
            pipeServer1 = gcnew NamedPipeServerStream("\\\\.\\pipe\\testpipe1", PipeDirection::InOut, numThreads);
            pipeServer2 = gcnew NamedPipeServerStream("\\\\.\\pipe\\testpipe2", PipeDirection::InOut, numThreads);
        }
                                
        threadId = Thread::CurrentThread->ManagedThreadId;


        // İstemciden bir bağlantı bekleniyor
        pipeServer->WaitForConnection();

        Console::WriteLine("Client connected on thread.", threadId);
        try
        {  
          // Alt işlemin sırasına bağlı olarak, verileri adlandırılmış bir kanaldan diğerine kopyalayın.
          if (i == 0) {
            needclose = true;
            i++;
            // Sayaçtaki adlandırılmış kanallardan bilgi kopyalamak için başka bir alt süreç oluşturun
            Thread server = gcnew Thread(gcnew ThreadStart(&ServerThread));
            // Alt süreci başlatın
            server->Start();
            pipeServer1->CopyToAsync(pipeServer2);
          } else {
            pipeServer2->CopyToAsync(pipeServer1);
          }
        }
        // Düşen istemciler için istisna işleyicisi 
        catch (IOException^ e)
        {
            Console::WriteLine("ERROR: {0}", e->Message);
        }
        if (needclose) {
          pipeServer1->Close();
          pipeServer2->Close();
        }
     }
};

int main()
{
    PipeServer::Main();
}
 

MinGW kuruldu, yapılandırıldı ve NetBeans'e bağlandı.

İki sunucu kanalından tam çift yönlü bir ağ geçidi oluşturma ve bilgileri bir kanaldan diğerine istemcilere yeniden yönlendirme fikri işe yaramadı. Bir sunucu alt işlemi bir kanalı okur ve ikincisi ona bir şey gönderirse, tam çift yönlü çalışmaz (en azından Windows XP'de), çünkü bazen kanaldan okuyan alt işlem, aynı kanala yazan alt işlemden gelen mesajları keser ve bilgileri geri döndürür.

Alt işlemlerden birini kaldırırsanız, iletim istemciden istemciye sorunsuz bir şekilde tek yönlü olarak gider.

Bununla birlikte, her şey kaybolmaz, çünkü örtüşen bir mod da vardır, yani iki değil, sadece bir kanal oluşturulduğunda ve birkaç istemci aynı anda ona bağlandığında. Bu durumda sunucunun her zaman kanaldan bilgi okumasına gerek yoktur, çünkü her şey olaylara dayanır. Yani, herhangi bir istemci kanala bilgi gönderirse, sunucu onun olayını okur ve iletilen mesajı oradan çıkarır. Ve alınan bilgiyi ikinci istemciye yönlendirmek - bu zaten bir teknik meselesi. Böyle bir uygulama oluşturma sürecindeyim.

 

Bu kadar. Vazgeçtim. C++ koduyla ve hatta Win API ile uğraşmaktan yoruldum. Her şeyin nasıl çalışması gerektiğini anlamaya çalışmak için MSDN'deki dağınık bilgi parçalarını araştırmak kadar kodlama değil. Deneyim eksik, bu yüzden tüm bu şeyleri Servis Çalışmasına gönderdim. C++ kodunu iki yönlü tam çift yönlü bir ağ geçidine dönüştürün

Belki daha deneyimli biri bu işi kolayca halledebilir? Başarısızlıkların nedeninin adlandırılmış kanalların ayarlarını çözemediğimden kaynaklandığını göz ardı etmiyorum. Yani, bu ayarlarda doğru bir şey yazmanız gerekiyor olabilir ve her şey çalışabilir. Şimdiye kadar simpleks moddan başka bir şey yapmayı ve çalıştırmayı başaramadım.

 

Boru hatları aracılığıyla MQL ve AutoIt arasında dostluk kurmaya karar verdim.

Kısacası, sadece bir tırmık ve her yerde :)

Biraz şansla AutoIt'e aktarmayı başardım, sadece ilk 4 baytın atılması gerekiyordu, bazı "çöpler" var. Bu "saçmalık" nedir?

Sonra MQL'e aktarmayı denedim, burası daha da eğlenceli - hiçbir şey gelmiyor. Ya da belki de aktarımı doğru organize etmiyorum.... Belki de tüm sorun bu 4 bayttadır?

Bana ne söyleyebilirsiniz?

 
fyords:

Boru hatları aracılığıyla MQL ve AutoIt arasında dostluk kurmaya karar verdim.

Kısacası, sadece bir tırmık ve her yerde :)

Biraz şansla AutoIt'e aktarmayı başardım, sadece ilk 4 baytın atılması gerekiyordu, bazı "çöpler" var. Bu "saçmalık" nedir?

Sonra MQL'e aktarmayı denedim, burası daha da eğlenceli - hiçbir şey gelmiyor. Ya da belki de aktarımı doğru organize etmiyorum.... Belki de tüm sorun bu 4 bayttadır?

Bana ne söyleyebilirsin?

Sho, sen de mi?
Клуб Телепатов - MQL4 форум
  • www.mql5.com
Клуб Телепатов - MQL4 форум
 
sergeev:
Yani sen de mi oradasın?

Hayır, buradayım.) Yani, şöyle oldu:

MQL5

#include <Files\FilePipe.mqh>

CFilePipe  ExtPipe;
//+------------------------------------------------------------------+
//| Komut dosyası programı başlatma işlevi|
//+------------------------------------------------------------------+
void OnStart()
  {
//--- boru sunucusunu bekleyin
   while(!IsStopped())
     {
      if(ExtPipe.Open("\\\\.\\pipe\\MQL5.Pipe.Server",FILE_READ|FILE_WRITE|FILE_BIN|FILE_ANSI)!=INVALID_HANDLE) break;
      Sleep(250);
     }
   Print("Client: pipe opened");
//--- hoş geldiniz mesajı gönder
   string msg=__FILE__+" on MQL5 build "+IntegerToString(__MQ5BUILD__);
   //Print(msg);
   
   if(!ExtPipe.WriteString(msg))
     {
      Print("Client: sending welcome message failed");
      return;
     }
  }

AutoIt

#include <NamedPipes.au3>
#include <WinAPI.au3>

$pipe="\\.\pipe\MQL5.Pipe.Server"
$hwnd_pipe=_NamedPipes_CreateNamedPipe($pipe) ;//Creates an instance of a named pipe
_NamedPipes_ConnectNamedPipe($hwnd_pipe) ;//named pipe sunucu işleminin bir istemci işleminin bağlanmasını beklemesini sağlar
ConsoleWrite(ReadMsg($hwnd_pipe)) ;//Verileri STDOUT akışına yazar

Func ReadMsg($hPipe) ;//ReadMsg
        Local $bSuccess, $iRead, $pBuffer, $tBuffer, $BUFSIZE=4096

        $tBuffer = DllStructCreate("char Text[4096]")
        $pBuffer = DllStructGetPtr($tBuffer)
        _WinAPI_ReadFile($hPipe, $pBuffer, 4, $iRead, 0)
        While 1
                $bSuccess = _WinAPI_ReadFile($hPipe, $pBuffer, $BUFSIZE, $iRead, 0)
                If $iRead = 0 Then ExitLoop
                If Not $bSuccess Or (_WinAPI_GetLastError() = 234) Then ExitLoop
                Return StringLeft(DllStructGetData($tBuffer, "Text"), $iRead)
        WEnd
 EndFunc
 
 Func WriteMsg($hPipe,$sMessage) ;//WriteMsg
        Local $iWritten, $iBuffer, $pBuffer, $tBuffer

        $iBuffer = StringLen($sMessage) + 1
        $tBuffer = DllStructCreate("char Text[" & $iBuffer & "]")
        $pBuffer = DllStructGetPtr($tBuffer)
        DllStructSetData($tBuffer, "Text", $sMessage)
        If Not _WinAPI_WriteFile($hPipe, $pBuffer, $iBuffer, $iWritten, 0) Then
                LogError("WriteMsg: _WinAPI_WriteFile failed")
        EndIf
EndFunc

MQL'den AutoIt'e aktarımın bu kısmı. Şu şekilde çalışır.

Func ReadMsg($hPipe)'dan bir dize ile

_WinAPI_ReadFile($hPipe, $pBuffer, 4, $iRead, 0)

İlk 4 baytı yiyorum ve her şey çalışıyor.

Soru: Bu ilk 4 bayt ne içeriyor?

 
fyords:

İlk 4 baytı yiyorum ve her şey çalışıyor.

Soru: Bu ilk 4 bayt ne içeriyor?

Dizeleri iletirken, dize boyutunun 4 baytı önce gelir.
 
Dima_S:
Renat, MT4'te pip yapılması ne zaman planlanıyor?
MetaTrader 4'ün son yapısında yapıldılar.