Скачать MetaTrader 5

Проблема с импортированными системными функциями

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
Опубликуй задачу в сервисе Фриланс и разработчики выполнят ее.
vasya-gaykin
48
vasya-gaykin 2014.11.10 12:01 

День добрый.

Проблема с вызовами функций из системных dll. Задача -- написать простенький сервер TCP на MQL5, к-ый висит на определенном порту и просто принимает сообщения.

Импортировал из ws2_32.dll функции WSAStartup(), WSAClenup(), socket(), bind(), accept(), listen(), recv(). Все работает ровно до того, пока не попытаешься остановить сервер. После попытки остановит сервер и корректно завершить работу скрипта, терминал просто вылетает.

Методом научного тыка вышел на функцию recv().

в прикрепленном файле есть строчка (171):

  int bytesCnt = recv(clientSocket, rcvBuffer, RCVBUFFSIZE, 0);

если ее привести к виду:

  int bytesCnt = 10; //recv(clientSocket, rcvBuffer, RCVBUFFSIZE, 0);

то сервер останавливается безо всяких ошибок. Примеры использования ф-ий для работы с сетью смотрел на MSDN и все сделал по аналогии.

Получается, что из-за использования ф-ии recv() возникают какие-то побочные эффекты.

Есть ли у кого-нибудь идеи как решить проблему?

Файлы:
Koldun Zloy
228
Koldun Zloy 2014.11.11 17:23  
При работе с динамическими библиотеками имеет значение разрядность терминала.
Для 64-разрядного терминала определяем такой макрос:
#define _WIN64  // Только для 64-разрядного терминала!

Дальше выкладываю Ваш исправленный пример.

#ifdef _WIN64
#define PVOID ulong
#else
#define PVOID uint
#endif

#define DWORD_PTR PVOID
#define SOCKET PVOID

#define BYTE uchar
#define WORD ushort
#define DWORD uint
#define UINT uint

#define AF_INET       2   // internetwork: UDP, TCP, etc.
#define SOCK_STREAM   1   // stream socket
#define IPPROTO_TCP   6   // tcp

#define MAKEWORD(a, b) ((WORD)(((BYTE)(((DWORD_PTR)(a)) & 0xff)) | ((WORD)((BYTE)(((DWORD_PTR)(b)) & 0xff))) << 8))

#define WSADESCRIPTION_LEN  256
#define WSASYS_STATUS_LEN   128
#define RCVBUFFSIZE         1024

struct WSADATA
{
   WORD     wVersion;
   WORD     wHighVersion;
#ifdef _WIN64
   ushort   iMaxSockets;
   ushort   iMaxUdpDg;
   PVOID    lpVendorInfo;
   char     szDescription[WSADESCRIPTION_LEN+1];
   char     szSystemStatus[WSASYS_STATUS_LEN+1];
#else
   char     szDescription[WSADESCRIPTION_LEN+1];
   char     szSystemStatus[WSASYS_STATUS_LEN+1];
   ushort   iMaxSockets;
   ushort   iMaxUdpDg;
   PVOID    lpVendorInfo;
#endif
};

#define INVALID_SOCKET (SOCKET)(~0)

#define IN_ADDR uint
#define INADDR_ANY (uint)0x00000000

struct SOCKADDR_IN
{
   short   sin_family;
   ushort  sin_port;
   IN_ADDR sin_addr;
   char    sin_zero[8];
};

#import "Ws2_32.dll"
   int WSAStartup( ushort wVersionRequested, WSADATA& lpWSAData );
   int WSACleanup();
   int WSAGetLastError();
    
   SOCKET socket( int af, int type, int protocol );
   int shutdown( SOCKET socket, int how );
   int closesocket( SOCKET socket );
   
   int bind( SOCKET socket, SOCKADDR_IN& lpSockAddr, int size );
   int listen( SOCKET socket, int backlog );
   int accept( SOCKET socket, PVOID a=0, PVOID b=0 );
   int recv( SOCKET socket, char& lpBuffer[], int bufferLen, int flags );
   
   ushort ntohs( ushort number );
   ushort htons( ushort number );  
#import

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
   // dll initialization
   WORD wVersionRequested = MAKEWORD( 2, 2 );
   WSADATA wsaData;
   int errno = WSAStartup( wVersionRequested, wsaData );
   if( errno != 0 ){
      ErrorLog( "WSAStartup", errno );
      return;
   }
   
   // make listen socket
   SOCKET serverSocket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
   if( serverSocket == INVALID_SOCKET )
   {
      ErrorLog( "socket", WSAGetLastError() );
      WSACleanup();
      return;
   }
   
   // bind to port
   SOCKADDR_IN service;
   service.sin_family = AF_INET;
   ushort portNumber = 13313;
   Print( "Bind to port ", portNumber );
   service.sin_port = htons( portNumber );
   service.sin_addr = INADDR_ANY;

   errno = bind( serverSocket, service, sizeof(service) );
   if( errno != 0 )
   {
      ErrorLog( "bind", WSAGetLastError() );
      closesocket( serverSocket );
      WSACleanup();
      return;
   }
   
   errno = listen( serverSocket, 1 );
   if( errno != 0 )
   {
      ErrorLog( "listen", WSAGetLastError() );
      closesocket( serverSocket );
      WSACleanup();
      return;
   }
   
   // wait for incoming connection
   SOCKET clientSocket = accept( serverSocket, 0, 0 );
   if( clientSocket == INVALID_SOCKET )
   {
      ErrorLog( "accept", WSAGetLastError() );
      closesocket( serverSocket );
      WSACleanup();
      return;
   }
   
   // wait for incoming data
   char rcvBuffer[RCVBUFFSIZE];
   int bytesCnt = recv( clientSocket, rcvBuffer, RCVBUFFSIZE, 0 );
   if( bytesCnt > 0 )
   {
      Print( "Received ", bytesCnt, " bytes" );
   }
   else if( bytesCnt == 0 )
   {
      Print( "Connection closed" );
   }
   else
   {
      ErrorLog( "recv", WSAGetLastError() );
   }
   
   // dll clenup
   closesocket(clientSocket);
   closesocket(serverSocket);   
   WSACleanup();
}
//+------------------------------------------------------------------+
void ErrorLog( string functionName, int errno )
{
   Print( "\"", functionName, "()\" has failure with error code: ", errno, " see winsock erorr codes" );
}
//+------------------------------------------------------------------+
vasya-gaykin
48
vasya-gaykin 2014.11.11 18:41  
danke schon!
Alexey Klenov
1884
Alexey Klenov 2015.04.07 07:17  

пробую реализовать отправку пакета из индикатора по протоколу UDP

свиду уходит пакет но до адресата на C# данный пакет ее приходит 

если внутри C# пробовать отправить пакет то проблем нет

вот код индикатора

//+------------------------------------------------------------------+
//|                                                   SendProfit.mq4 |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_chart_window


#ifdef _WIN64
#define PVOID ulong
#else
#define PVOID uint
#endif

#define DWORD_PTR PVOID
#define SOCKET PVOID

#define BYTE uchar
#define WORD ushort
#define DWORD uint
#define UINT uint

#define AF_INET       2   // internetwork: UDP, TCP, etc.
#define SOCK_STREAM   1   // stream socket
#define SOCK_DGRAM      2               // datagram socket 
#define SOCKET_ERROR            (-1)
#define IPPROTO_UDP             17              // user datagram protocol 

#define IPPROTO_TCP   6   // tcp

#define MAKEWORD(a, b) ((WORD)(((BYTE)(((DWORD_PTR)(a)) & 0xff)) | ((WORD)((BYTE)(((DWORD_PTR)(b)) & 0xff))) << 8))

#define WSADESCRIPTION_LEN  256
#define WSASYS_STATUS_LEN   128
#define RCVBUFFSIZE         1024
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
struct WSADATA
  {
   WORD              wVersion;
   WORD              wHighVersion;
#ifdef _WIN64
   ushort            iMaxSockets;
   ushort            iMaxUdpDg;
   PVOID             lpVendorInfo;
   char              szDescription[WSADESCRIPTION_LEN+1];
   char              szSystemStatus[WSASYS_STATUS_LEN+1];
#else
   char              szDescription[WSADESCRIPTION_LEN+1];
   char              szSystemStatus[WSASYS_STATUS_LEN+1];
   ushort            iMaxSockets;
   ushort            iMaxUdpDg;
   PVOID             lpVendorInfo;
#endif
  };

#define INVALID_SOCKET (SOCKET)(~0)

#define IN_ADDR uint
#define INADDR_ANY (uint)0x00000000
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
struct SOCKADDR_IN
  {
   short             sin_family;
   ushort            sin_port;
   IN_ADDR           sin_addr;
   char              sin_zero[8];
  };

#import "Ws2_32.dll"
int WSAStartup(ushort wVersionRequested,WSADATA &lpWSAData);
int WSACleanup();
int WSAGetLastError();

SOCKET socket(int af,int type,int protocol);
int shutdown(SOCKET socket,int how);
int closesocket(SOCKET socket);

int bind(SOCKET socket,SOCKADDR_IN &lpSockAddr,int size);
int listen(SOCKET socket,int backlog);
int accept(SOCKET socket,PVOID a=0,PVOID b=0);
int recv(SOCKET socket,char &lpBuffer[],int bufferLen,int flags);
int send(SOCKET s,char &buf[],int len,int flags);

int sendto(SOCKET s,char &buf[],int len,int flags,SOCKADDR_IN &to,int tolen);

ushort ntohs(ushort number);
ushort htons(ushort number);
uint inet_addr(char &cp[]);
#import

SOCKET serverSocket;//sSocketSender;
SOCKADDR_IN service;
SOCKADDR_IN RemoteIPPort;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
// dll initialization
   WORD wVersionRequested=MAKEWORD(2,2);
   WSADATA wsaData;
   int errno= WSAStartup(wVersionRequested,wsaData);
   if(errno!=0)
     {
      ErrorLog("WSAStartup",errno);
      return(INIT_FAILED);
     }

// make listen socket
//serverSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
   serverSocket=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
   if(serverSocket==INVALID_SOCKET)
     {
      ErrorLog("socket",WSAGetLastError());
      WSACleanup();
      return(INIT_FAILED);
     }

// bind to port

   service.sin_family= AF_INET;
   ushort portNumber = 3795;


   service.sin_port=htons(portNumber);
//service.sin_addr = INADDR_ANY;
   char charAdd[];
   StringToCharArray("127.0.0.1",charAdd,0,-1,CP_ACP);
   service.sin_addr=inet_addr(charAdd);

   RemoteIPPort.sin_family=AF_INET;
   RemoteIPPort.sin_port=htons(3795);
   StringToCharArray("192.168.1.10",charAdd,0,-1,CP_ACP);
   RemoteIPPort.sin_addr=inet_addr(charAdd);

   errno=bind(serverSocket,service,sizeof(service));
   if(errno!=0)
     {
      ErrorLog("bind",WSAGetLastError());
      closesocket(serverSocket);
      WSACleanup();
      return(INIT_FAILED);
     }
   else
     {Print("Bind to port ",portNumber);}

   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
  {
//closesocket(clientSocket);
   closesocket(serverSocket);
   WSACleanup();
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   char str[];
   string sToSend="12257:1257.5";
   StringToCharArray(sToSend,// строка-источник
                     str,// массив
                     0,             // начальная позиция в массиве
                     -1,            // количество символов
                     CP_ACP      // кодовая страница
                     );

   DWORD res=sendto(serverSocket,str,StringLen(sToSend),0,RemoteIPPort,sizeof(RemoteIPPort));//==SOCKET_ERROR
   Comment(res);

   return(rates_total);
  }
//+------------------------------------------------------------------+
void ErrorLog(string functionName,int errno)
  {
   Print("\"",functionName,"()\" has failure with error code: ",errno," see winsock erorr codes");
  }
//+------------------------------------------------------------------+

В комментарий пишет 12 (тоесть ошибки отправки нет)

Подскажите что не так.

///

Вопрос снят сам разобрался

Eugeniy Lugovoy
1979
Eugeniy Lugovoy 2015.04.07 20:53  
olyakish:

пробую реализовать отправку пакета из индикатора по протоколу UDP

свиду уходит пакет но до адресата на C# данный пакет ее приходит 

если внутри C# пробовать отправить пакет то проблем нет

вот код индикатора

В комментарий пишет 12 (тоесть ошибки отправки нет)

Подскажите что не так.

///

Вопрос снят сам разобрался

И что было не так? Подскажите всем.
Alexey Klenov
1884
Alexey Klenov 2015.07.09 23:29  

Код индикатора отправляющего эквити из терминала далее по UDP (большая часть индикатора не моя)

//+------------------------------------------------------------------+
//|                                                   SendProfit.mq4 |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.05"
#property strict
#property indicator_chart_window

extern string remoteIP="0.0.0.0";         // Удаленный IP  для сбора эквити
extern int  remotePort=3093;                // Удаленный  порт для сбора эквити (как portForGetEquaty)

#ifdef _WIN64
#define PVOID ulong
#else
#define PVOID uint
#endif

#define DWORD_PTR PVOID
#define SOCKET PVOID

#define BYTE uchar
#define WORD ushort
#define DWORD uint
#define UINT uint

#define AF_INET       2   // internetwork: UDP, TCP, etc.
#define SOCK_STREAM   1   // stream socket
#define SOCK_DGRAM      2               // datagram socket 
#define SOCKET_ERROR            (-1)
#define IPPROTO_UDP             17              // user datagram protocol 

#define IPPROTO_TCP   6   // tcp

#define MAKEWORD(a, b) ((WORD)(((BYTE)(((DWORD_PTR)(a)) & 0xff)) | ((WORD)((BYTE)(((DWORD_PTR)(b)) & 0xff))) << 8))

#define WSADESCRIPTION_LEN  256
#define WSASYS_STATUS_LEN   128
#define RCVBUFFSIZE         1024
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
struct WSADATA
  {
   WORD              wVersion;
   WORD              wHighVersion;
#ifdef _WIN64
   ushort            iMaxSockets;
   ushort            iMaxUdpDg;
   PVOID             lpVendorInfo;
   char              szDescription[WSADESCRIPTION_LEN+1];
   char              szSystemStatus[WSASYS_STATUS_LEN+1];
#else
   char              szDescription[WSADESCRIPTION_LEN+1];
   char              szSystemStatus[WSASYS_STATUS_LEN+1];
   ushort            iMaxSockets;
   ushort            iMaxUdpDg;
   PVOID             lpVendorInfo;
#endif
  };

#define INVALID_SOCKET (SOCKET)(~0)

#define IN_ADDR uint
#define INADDR_ANY (uint)0x00000000
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
struct SOCKADDR_IN
  {
   short             sin_family;
   ushort            sin_port;
   IN_ADDR           sin_addr;
   char              sin_zero[8];
  };

#import "Ws2_32.dll"
int WSAStartup(ushort wVersionRequested,WSADATA &lpWSAData);
int WSACleanup();
int WSAGetLastError();

SOCKET socket(int af,int type,int protocol);
int shutdown(SOCKET socket,int how);
int closesocket(SOCKET socket);

int bind(SOCKET socket,SOCKADDR_IN &lpSockAddr,int size);
int listen(SOCKET socket,int backlog);
int accept(SOCKET socket,PVOID a=0,PVOID b=0);
int recv(SOCKET socket,char &lpBuffer[],int bufferLen,int flags);
int send(SOCKET s,char &buf[],int len,int flags);

int sendto(SOCKET s,char &buf[],int len,int flags,SOCKADDR_IN &to,int tolen);

ushort ntohs(ushort number);
ushort htons(ushort number);
uint inet_addr(char &cp[]);
#import

SOCKET serverSocket;//sSocketSender;
SOCKADDR_IN service;
SOCKADDR_IN RemoteIPPort;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
// dll initialization
   WORD wVersionRequested=MAKEWORD(2,2);
   WSADATA wsaData;
   int errno= WSAStartup(wVersionRequested,wsaData);
   if(errno!=0)
     {
      ErrorLog("WSAStartup",errno);
      return(INIT_FAILED);
     }

// make listen socket

   serverSocket=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
   if(serverSocket==INVALID_SOCKET)
     {
      ErrorLog("socket",WSAGetLastError());
      WSACleanup();
      return(INIT_FAILED);
     }

// bind to port

   service.sin_family=AF_INET;

   ushort portNumber=3000;  // с какого порта отправляем
   service.sin_addr=INADDR_ANY;
   for(int i=0;i<100;i++)
     {
     // поиск свободного порта
      service.sin_port=htons(portNumber+i);
      errno=bind(serverSocket,service,sizeof(service));
      if(errno!=0)
        {
         //ErrorLog("bind",WSAGetLastError());
         //closesocket(serverSocket);
         //WSACleanup();
         //return(INIT_FAILED);
        }
      else
        {Print("Bind to port ",portNumber+i);break;}
     }

   char charAdd[];
   RemoteIPPort.sin_family=AF_INET;
   RemoteIPPort.sin_port=htons(remotePort);  // на какой порт отправляем 
   StringToCharArray(remoteIP,charAdd,0,-1,CP_ACP);

   RemoteIPPort.sin_addr=inet_addr(charAdd);

   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
  {
//closesocket(clientSocket);
   closesocket(serverSocket);
   WSACleanup();
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   char str[];
   string sToSend=AccountInfoInteger(ACCOUNT_LOGIN)+":"+AccountProfit();
   StringToCharArray(sToSend,// строка-источник
                     str,// массив
                     0,             // начальная позиция в массиве
                     -1,            // количество символов
                     CP_ACP      // кодовая страница
                     );


   DWORD res=sendto(serverSocket,str,StringLen(sToSend),0,RemoteIPPort,sizeof(RemoteIPPort));//==SOCKET_ERROR
                                                                                             //Print(sToSend+" "+res);
   return(rates_total);
  }
//+------------------------------------------------------------------+
void ErrorLog(string functionName,int errno)
  {
   Print("\"",functionName,"()\" has failure with error code: ",errno," see winsock erorr codes");
  }
//+------------------------------------------------------------------+


В C#  (основа)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.IO.MemoryMappedFiles;
namespace mytest
{
    public partial class Form1 : Form
    {
        public Thread tRecEquaty;
        public UdpClient receivingUdpClient;
        public int maxAccount = 0; // будет увеличиваться по мере поступления новых данных от счетов
        public profit[] allProfit = new profit[100]; //например, возьмем длину массива = 100
        public IPEndPoint ThisIpEndPoint;
        private void Form1_Load(object sender, EventArgs e)
        {
           ThisIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
           receivingUdpClient = new UdpClient(3093);
           tRecEquaty = new Thread(new ThreadStart(Receiver_GetEquaty));
           tRecEquaty.Start();
        }
        public void Receiver_GetEquaty()
        {
            try
            {
                while (true)
                {
                    // Ожидание дейтаграммы
                    byte[] receiveBytes = receivingUdpClient.Receive(ref ThisIpEndPoint);

                    // Преобразуем и отображаем данные
                    string returnData = Encoding.UTF8.GetString(receiveBytes);

                    string[] str = returnData.Split(':');

                    int i = 0;
                    for (i = 0; i < maxAccount; i++)
                    {
                        if (str[0].ToString() == allProfit[i].accID)
                        {
                            break;
                        }
                    }
                    allProfit[i].accID = str[0].ToString();
                    allProfit[i].Equaty = Convert.ToDecimal(str[1]);
                    if (i == maxAccount)
                    { maxAccount++; }
                    decimal allSumm = 0.0m;
                    if (maxAccount > 0)
                    {
                       for (int i = 0; i < maxAccount; i++)
                        {
                          allSumm += allProfit[i].Equaty;
                        }
                      if (allSumm != 0.0m)
                       { lProfit.Text = allSumm.ToString("#.#"); }
                      else
                       { lProfit.Text = "Profit"; }

                     if (allSumm < 0.0m) { lProfit.ForeColor = Color.FromName("Red"); }
                     if (allSumm > 0.0m) { lProfit.ForeColor = Color.FromName("DarkGreen"); }
                     if (allSumm == 0.0m) { lProfit.ForeColor = Color.FromName("Orange"); }
                   }
                }
            }
            catch (Exception ex)
            {
                //Console.WriteLine("Возникло исключение: " + ex.ToString() + "\n  " + ex.Message);
            }
        }
   }
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий