Uzman Danışmanlar: Yatırımcılar için MQL5 Programlama - Kitaptan kaynak kodları. Bölüm 7 - sayfa 3

 
Websockets sınıflarındaki bazı hata düzeltmelerini ve iyileştirmeleri ekliyorum.
Dosyalar:
wss.zip  16 kb
 
Stanislav Korotky #:
Websockets sınıflarındaki bazı hata düzeltmelerini ve iyileştirmeleri ekliyorum.
Çabalarınız için teşekkür ederim
 
Stanislav Korotky #:
Ekonomik takvim okuma ve CSV'ye aktarma için daha fazla hata düzeltmesi ve iyileştirme kod tabanında yayınlandı. Özellikle, sıralama algoritması çoğunlukla sıralanmış büyük diziler (genellikle MQL5 takvim API'sinden alınan) için düzeltildi, böylece yavaşlamalar ve yığın taşmaları ortadan kaldırıldı.

msclient.mqh satırında küçük bir bud var 126 'return connection.handshake(url, host, origin, custom_headers);' 'yol' yerine tam 'url'yi geçmek python websocket'te 403 hatasına yol açar. EA'nın python websocket sunucuma başarıyla bağlanabilmesi için bu değişikliği yapmak zorunda kaldım.
Değişikliği yapmadan önce Postman (geçti) ve EA'dan sunucu günlüğünü ekledim (başarısız oldu)

Ancak bir sonraki sorun şu, sunucum yapılandırılmış bir aralıkta otomatik olarak bir keepalive ping gönderiyor, ancak MT5 websocket uygulaması yanıt vermiyor gibi görünüyor ve bu davranış sunucunun ping zaman aşımından hemen sonra istemci bağlantısını her zaman bırakmasına neden oluyor.

Lütfen keepalive ping pong ile ilgili herhangi bir yardım takdir edilecektir

Dosyalar:
passed.png  88 kb
failed.png  50 kb
 
pauldic #:

msclient.mqh satırında küçük bir bud var 126 'return connection.handshake(url, host, origin, custom_headers);' 'yol' yerine tam 'url'yi geçmek python websocket'te 403 hatasına yol açar. EA'nın python websocket sunucuma başarıyla bağlanabilmesi için bu değişikliği yapmak zorunda kaldım.
Değişikliği yapmadan önce Postman (geçti) ve EA'dan sunucu günlüğünü ekledim (başarısız)

Ancak bir sonraki sorun şu, sunucum yapılandırılmış bir aralıkta otomatik olarak bir keepalive ping gönderiyor, ancak MT5 websocket uygulaması yanıt vermiyor gibi görünüyor ve bu davranış sunucunun ping zaman aşımından hemen sonra istemci bağlantısını her zaman bırakmasına neden oluyor.

Lütfen keepalive ping pong ile ilgili herhangi bir yardım takdir edilecektir

Merhaba, evet istemci çağrısında path kullanabilirsiniz:

template<typename T>
class WebSocketClient: public IWebSocketObserver
{
   ...
   bool open(const string custom_headers = NULL)
   {
      ...
      connection = new T(&this, socket, compression);
      return connection.handshake(path, host, origin, custom_headers);
   }

Öte yandan, HTTP istek sözdizimi hedef olarak tam URI'yi destekler ve orijinal kaynak kodlarıyla farklı sunuculara karşı testler yaptım ( wss://ws.postman-echo.com/raw dahil) ve normal şekilde çalıştılar. Yani bu bir ihlal mi yoksa python'unuzun uygulaması bir anlamda çok mu katı emin değilim.

Ping/pong'a gelince, çalışması gerekir. Wsprotocol.mqh dosyasına bir göz atın :

   // Gelen kontrol çerçevelerini işleyin: Ping üzerine Pong gönderir ve bir Kapatma isteğinden sonra bağlantıyı kapatır
   void processControlFrame(IWebSocketFrame *frame)
   {
      switch(frame.getType())
      {
      case WS_FRAME_OPCODE::WS_CLOSE_FRAME:
         if(closeRequested) // kapanışımız onaylandı
         {
            Print("Server close ack");
         }
         else if(!disconnecting) // sunucu tarafından başlatılan kapatma
         {
            if(openMessage) // hala sonuçlandırılmadı(!)
            {
               owner.onMessage(openMessage);
               openMessage = NULL;
            }
          
            WebSocketFrame temp(WS_FRAME_OPCODE::WS_CLOSE_FRAME); // ack'ımızı gönder
            sendFrame(&temp);
         }
         close();
         break;
      case WS_FRAME_OPCODE::WS_PING_FRAME:
         {
            IWebSocketFrame *temp = WebSocketFrame::create(WS_FRAME_OPCODE::WS_PONG_FRAME, frame.getData());
            sendFrame(temp);
            delete temp;
         }
         break;
      }
   }

Sunucu istemcinize ping gönderdiğinden, lütfen kendi tarafınızda bu şeylerin hatalarını ayıklayın.

 
Bu arada, ws/kaynaklarında kullanılan MQL5Book/StringUtils.mqh dosyasının yeni sürümünü eklemeyi unuttum.
Dosyalar:
 
Stanislav Korotky #:
Bu arada, ws/sources'da kullanılan MQL5Book/StringUtils.mqh 'nin yeni sürümünü eklemeyi unuttum.
@Stanislav Korotky yardımınız için tekrar teşekkürler. Python websocket sunucusu ile ping pong sorunu ile ilgili olarak, daha fazla hata ayıklama üzerine sunucunun ping isteğini metin veya ikili veri olarak gönderdiğini ve MT5'in yalnızca metin tabanlı bir ping gönderildiğinde başarıyla yanıt verdiğini fark ettim. Bu, sorunu bulmama ve düzeltmeme yardımcı oldu.

Sorun, websocket çerçevesi oluşturulduğunda ws ping çerçeve anahtarı / durumu içindeki 310. satırdadır:

IWebSocketFrame *temp = WebSocketFrame::create(WS_FRAME_OPCODE::WS_PONG_FRAME, frame.getData());

frame.getData() sunucu sadece ping verisi metin/dize tabanlı ise pong'u kabul ediyor gibi görünüyor ancak ikili ping gönderilmişse başarısız oluyor

bu nedenle her iki durumda da çalışmasını sağlamak için aşırı yüklenmiş frame.getData(uchar &buf[]) kullanmam gerekiyor. (Değişikliğimin) bozacağı başka kullanım durumlarıyla karşılaşır mıyım bilmiyorum ama şimdilik her şey yolunda görünüyor.


uchar data[]
; frame.getData(data)
; IWebSocketFrame *temp = WebSocketFrame::create(WS_FRAME_OPCODE::WS_PONG_FRAME, data);

Sadece meraktan soruyorum, OnMessage gelen mesajlar için bir olay işleyici işlevi gibi görünen bir şey görürken, neden OnTimer() olay işleyicisi ile aralıklarla mesajları manuel olarak kontrol etmemiz gerektiğini merak ediyorum. Mevcut kurulum olduğu gibi çalışıyor olsa da, bu yaklaşımın nedenini daha fazla aydınlatabilirseniz sevinirim
 
pauldic #:
Stanislav Korotky yardımınız için tekrar teşekkürler. Python websocket sunucusu ile ping pong sorunu ile ilgili olarak, daha fazla hata ayıklama üzerine sunucunun ping isteğini metin veya ikili veri olarak gönderdiğini ve MT5'in yalnızca metin tabanlı bir ping gönderildiğinde başarıyla yanıt verdiğini fark ettim. Bu, sorunu bulmama ve düzeltmeme yardımcı oldu .

Sorun, websocket çerçevesi oluşturulduğunda ws ping çerçeve anahtarı / durumu içindeki 310. satırdadır:

IWebSocketFrame *temp = WebSocketFrame::create(WS_FRAME_OPCODE::WS_PONG_FRAME, frame.getData());

frame.getData() sunucu sadece ping verisi metin/dize tabanlı ise pong'u kabul ediyor gibi görünüyor ancak ikili ping gönderilmişse başarısız oluyor

bu nedenle her iki durumda da çalışmasını sağlamak için aşırı yüklenmiş frame.getData(uchar &buf[]) kullanmam gerekiyor. (Değişikliğimin) bozacağı başka kullanım durumlarıyla karşılaşır mıyım bilmiyorum ama şimdilik her şey yolunda görünüyor.


uchar data[]
; frame.getData(data)
; IWebSocketFrame *temp = WebSocketFrame::create(WS_FRAME_OPCODE::WS_PONG_FRAME, data);

Sadece meraktan soruyorum, OnMessage gelen mesajlar için bir olay işleyici işlevi gibi görünen bir şey görürken, neden OnTimer() olay işleyicisi ile aralıklarla mesajları manuel olarak kontrol etmemiz gerektiğini merak ediyorum. Mevcut kurulum olduğu gibi çalışıyor olsa da, bu yaklaşımın nedenini daha fazla aydınlatabilirseniz sevinirim

Çabalarınız için teşekkür ederim. Düzenlemelerinizi kaynak kodlara dahil etmeyi düşüneceğim.

OnTimer ve OnMessage'a gelince, bunlar uygulamanızda farklı işleme mantığı uygulamak isteyebileceğiniz için sağlanmıştır. Soketlerden okuma, belirtilen zaman aşımı ile MQL5 API düzeyinde engellenir. Bu nedenle, yalnızca yeni mesajları beklemek, işlemek ve otomatik olarak yanıtlar oluşturmakla ilgileniyorsanız, bunu engelleme modunda (okumada sonsuz zaman aşımı ile ve OnTimer olmadan) yapabilirsiniz - yani uygulama veri beklerken bir tür donmuş durumdadır. Ancak bir kullanıcı için duyarlı bir kullanıcı arayüzü sağlamanız gerekiyorsa (sohbet uygulamasında olduğu gibi), OnTimer-handler'da kısa okuma denemeleri için küçük bir zaman aşımı ayarlarsınız (zaman aşımına uğrarsa boş veri üretebilirler) ve aradaki kullanıcı eylemlerini izlersiniz.

 
Stanislav Korotky #:

Çabalarınız için teşekkür ederim. Düzenlemelerinizi kaynak kodlarına dahil etmeyi düşüneceğim.

OnTimer ve OnMessage'a gelince, bunlar uygulamanızda farklı işleme mantığı uygulamak isteyebileceğiniz için sağlanmıştır. Soketlerden okuma, belirtilen zaman aşımı ile MQL5 API düzeyinde engellenir. Bu nedenle, yalnızca yeni mesajları beklemek, işlemek ve otomatik olarak yanıtlar oluşturmakla ilgileniyorsanız, bunu engelleme modunda (okumada sonsuz zaman aşımı ile ve OnTimer olmadan) yapabilirsiniz - yani uygulama veri beklerken bir tür donmuş durumdadır. Ancak bir kullanıcı için duyarlı bir kullanıcı arayüzü sağlamanız gerekiyorsa (sohbet uygulamasında olduğu gibi), OnTimer-handler'da kısa okuma denemeleri için küçük bir zaman aşımı ayarlarsınız (zaman aşımına uğrarsa boş veri üretebilirler) ve aradaki kullanıcı eylemlerini izlersiniz.

Açıklama için tekrar teşekkür ederim @StanislavKorotky
 

İşte bir zip-arşivindeki wss kaynak kodlarının bir başka küçük hata düzeltmeleri ve iyileştirmeleri.

Diğer şeylerin yanı sıra artık başarısız yükseltmeyi analiz edebilir (örneğin, yetkilendirme gerekliyse ve 101 dışında bir durum kodu döndürülürse) ve önlem alabilirsiniz:

if(wss.open(initial_headers))
{
   // başarılı, normal akış
}
else
{
  // bir şeyler ters gitti - yükseltme yapılmadı veya bağlanılmadı
  if(wss.isConnected())
  {
     Print("Can't upgrade to websockets");
     bool resolved = false;
     string headers[][2]; // response
     if(wss.getHeaders(headers))
     {
       // TODO: durumu analiz edin ve çözün
       resolved = ... // doğru/yanlış
     }
     if(!resolved)
     {
       wss.close(); // yükseltilmemiş soketten daha fazla okuma/yazma girişimini önlemek için kapat
     }
     else
     {
       wss.open(updated_headers); // try again
     }
  }
}

Ayrıca StringUtils.mqh ve URL.mqh de önemli düzeltmeler aldı.

Dosyalar:
wss.zip  16 kb
URL.mqh  5 kb
 

Merhaba @Stanislav Korotky, MQL5'te yeniyim. Websocket kullanımı için bir wss.zip dosyası yayınladığınızı gördüm. Nasıl kullanılır, bir demo veya öğrenebileceğim bir şey var mı? İçtenlikle teşekkür ederim!

Stanislav Korotky
Stanislav Korotky
  • 2025.04.07
  • www.mql5.com
Trader's profile