MQL5のWebRequestは便利ですが、
HTTP(S)でやり取りするサーバーにしか使えません。
独自の形式でデータをやり取りする社内サーバーや、
学習用のローカル検証サーバーと通信したい場合、
WebRequestだけでは手が止まってしまいます。
この記事では、SocketCreate・SocketConnectなどの
ソケット関数を使って、MQL5からTCP通信を
直接行う方法を、実際に動くスクリプトのコード付きで解説します。
・WebRequestとSocket関数の役割の違い
・SocketCreate〜SocketConnectで接続する手順
・ツールオプションでの許可アドレス登録
・SocketSend/SocketReadでデータを送受信する方法
なぜSocketConnectが必要になるのか
まず、WebRequestで足りない場面と、TCPソケットという仕組みの違いを確認します。
WebRequestはHTTP専用のクライアント
WebRequestは、HTTPリクエストを組み立てて送り、
レスポンスを受け取るところまでを1関数でやってくれる、
完成されたHTTPクライアントです。
SocketConnectは「生のTCP通信」を扱う
一方、SocketConnect系の関数が扱うのはTCPソケットそのもので、
HTTPのようなルールは何も用意されていません。
データの形式も受け取り方も、すべて自分で決める必要があります。
この記事で作るものの概要
| 関数群 | 役割 | 向いている場面 |
|---|---|---|
| WebRequest | HTTP(S)リクエストを送る | 一般的なWeb APIと通信する |
| SocketConnect系 | TCPソケットで直接通信する | 独自プロトコルのサーバーと通信する |
この記事では、文字列を送るとそのまま返してくる「エコーサーバー」
を例に、接続から送受信までの流れをスクリプトで作ります。
ソケット通信の基本的な流れ
ソケット通信は、電話をかけるときの手順に近い形で進みます。
SocketCreateでハンドルを作る
int socket = SocketCreate(SOCKET_DEFAULT);
まず、通信用の「電話機」に相当するハンドルを作ります。
失敗すると`INVALID_HANDLE`が返ります。
SocketConnectで接続する
bool ok = SocketConnect(socket, server, port, timeout_receive_ms);
作ったハンドルを使って、相手のサーバーに接続します。
第4引数の`timeout_receive_ms`は、接続待ちのタイムアウト時間です。
SocketIsConnectedで接続状態を確認する
bool connected = SocketIsConnected(socket);
接続直後にSocketIsConnectedで状態を確認しておくと安全です。
許可アドレスの設定という落とし穴
ソケット通信で最初につまずきやすいのが、この設定忘れです。
ツール→オプションでのアドレス登録
MQL5公式リファレンスにも明記されている通り、
Socket関数で接続する相手のアドレスは、
事前にターミナルの許可リストへ登録しておく必要があります。
・MT5のメニュー「ツール→オプション→EA」を開く
・「WebRequestを許可するURLリスト」に相当する欄へ接続先アドレスを追加する
・WebRequestのURL登録と同じ画面で管理される
登録を忘れると起きること
・登録忘れだとSocketConnectがfalseを返すだけで分かりにくい
・まずは許可リストの登録を確認するのが近道です
・デモ口座・実弾口座どちらでも同じ設定が必要です
ローカルの検証サーバーで試す方法
本番サーバーがまだない場合は、
自分のPCで動く簡単なエコーサーバーを用意し、
`127.0.0.1`(自分のPC自身)へ接続してテストすると
つまずきにくくなります。
データを送る・受け取る
接続できたら、実際に文字列を送って応答を受け取ります。
StringToCharArrayで送信用バイト列に変換する
uchar sendBuffer[]; int len = StringToCharArray(message, sendBuffer, 0, WHOLE_ARRAY, CP_UTF8) - 1;
SocketSendは文字列をそのまま送れないため、
一度バイト列(uchar配列)に変換する必要があります。
SocketSendで送信する
int sent = SocketSend(socket, sendBuffer, len);
戻り値は実際に送信できたバイト数です。
`-1`が返った場合はエラーなので、GetLastError()で原因コードを確認します。
SocketIsReadable→SocketReadで受信する
if(SocketIsReadable(socket) > 0)
{
int received = SocketRead(socket, recvBuffer, 1024, timeout_ms);
}
SocketIsReadableで「今読める量」を確認してから、
SocketReadで実際にデータを読み込む、という順序が安全です。
実際に動くコード全体
ここまでの関数を1つのスクリプトにまとめたコードです。
//+------------------------------------------------------------------+
//| SocketEchoClient.mq5 |
//| Copyright 2026, FX-EA System Project Creator |
//| https://creator.fx-ea-system-project.com/ |
//+------------------------------------------------------------------+
#property script_show_inputs
input string InpServer = "127.0.0.1";
input int InpPort = 9000;
input string InpMessage = "Hello from MQL5";
input uint InpTimeoutMs = 5000;
void OnStart()
{
int socket = SocketCreate(SOCKET_DEFAULT);
if(socket == INVALID_HANDLE)
{
Print("SocketCreate失敗 error=", GetLastError());
return;
}
if(!SocketConnect(socket, InpServer, InpPort, InpTimeoutMs))
{
Print("SocketConnect失敗 error=", GetLastError(),
" (接続先がツールオプションの許可アドレスに登録されているか確認してください)");
SocketClose(socket);
return;
}
if(!SocketIsConnected(socket))
{
Print("接続直後にSocketIsConnectedがfalseを返しました");
SocketClose(socket);
return;
}
uchar sendBuffer[];
int sendLen = StringToCharArray(InpMessage, sendBuffer, 0, WHOLE_ARRAY, CP_UTF8) - 1;
int sent = SocketSend(socket, sendBuffer, sendLen);
if(sent < 0)
{
Print("SocketSend失敗 error=", GetLastError());
SocketClose(socket);
return;
}
Print(sent, "バイト送信しました");
uint waited = 0;
while(SocketIsReadable(socket) == 0 && waited < InpTimeoutMs)
{
Sleep(100);
waited += 100;
}
uchar recvBuffer[];
ArrayResize(recvBuffer, 1024);
int received = SocketRead(socket, recvBuffer, 1024, InpTimeoutMs);
if(received > 0)
{
string reply = CharArrayToString(recvBuffer, 0, received, CP_UTF8);
Print("受信: ", reply);
}
else
{
Print("受信データなし、またはタイムアウト error=", GetLastError());
}
SocketClose(socket);
}
MetaEditorでのコンパイル・実行手順
- MetaEditorで新規スクリプト「SocketEchoClient」を作成し、上のコードを貼り付けてコンパイルする
- MT5の「ツール→オプション→EA」で接続先アドレス(127.0.0.1等)を許可リストへ追加する
- 自分のPCでエコーサーバーを起動しておく(無ければPython等で数行の学習用サーバーを用意する)
- ナビゲーターからチャートへスクリプトをドラッグ&ドロップして実行し、「エキスパート」タブで送受信ログを確認する
よくあるエラーと注意点
実際に使うときにつまずきやすいポイントをまとめます。
許可アドレス未登録によるSocketConnect失敗
最も多いのがこのケースです。
falseが返るだけで原因が分かりにくいため、
まず許可リストの登録を確認してください。
Sleep()を使っていい場所とダメな場所
・スクリプトのOnStart内はSleep()を使っても他の処理をブロックしない
・EAのOnTick内で同じようにSleep()を使うと、価格更新の処理が止まってしまう
・EAで待機処理が必要な場合はOnTimer(タイマーイベント)を使う設計にする
WebRequestとの使い分け、MQL4に相当する関数がない点
既刊のWebRequest関数の記事が扱う範囲はHTTP(S)通信のみなので、
独自プロトコルが必要な場面ではこの記事のSocket関数を使います。
なお、Socket関数はMQL5独自の機能で、MQL4には存在しません。
よくある質問
SocketConnectによるTCP通信について、よく検索される疑問に回答します。
ブローカーのサーバーと直接ソケット通信できますか?
この記事のSocket関数は、
あなたが用意した独自のサーバーと通信するためのものです。
ブローカーのサーバーとの通信はMT5本体の仕組みが担っているため、
Socket関数で直接やり取りする対象ではありません。
検証用のサーバーがない場合はどうすればいいですか?
Python等で、受け取った文字列をそのまま返すだけの
数行のプログラムを自分のPCで動かし、
127.0.0.1(自分のPC自身)へ接続するとすぐに試せます。
タイムアウトの値はどう決めればいいですか?
相手のサーバーの応答速度に応じて調整してください。
まずは既定値の5000ミリ秒前後から試し、
タイムアウトが頻発する場合は値を増やしてみてください。
【MQL5】WebRequestが使えない外部サービスへSocketConnectで直接つなぐTCP通信の作り方:まとめ
WebRequestはHTTP専用のクライアントのため、
独自プロトコルのサーバーとはSocketConnect系の関数で
直接TCP通信する必要があります。
SocketCreateで作ったハンドルをSocketConnectで接続し、
SocketSend・SocketReadで送受信する流れと、
ツールオプションでの許可アドレス登録を覚えておけば、
WebRequestが使えない場面にも対応できます。
コメント