Thiết lập và ngắt kết nối socket mạng
Trong các phần trước, chúng ta đã làm quen với các hàm mạng cấp cao của MQL5: mỗi hàm cung cấp hỗ trợ cho một giao thức ứng dụng cụ thể. Ví dụ, SMTP được sử dụng để gửi email (SendMail
), FTP được dùng để truyền tệp (SendFTP
), và HTTP cho phép nhận tài liệu web (WebRequest
). Tất cả các tiêu chuẩn được đề cập đều dựa trên tầng giao vận thấp hơn, TCP (Giao thức Điều khiển Truyền vận). Đây không phải là tầng cuối cùng trong hệ thống phân cấp vì còn có các tầng thấp hơn, nhưng chúng ta sẽ không thảo luận về chúng ở đây.
Việc triển khai tiêu chuẩn của các giao thức ứng dụng che giấu nhiều chi tiết kỹ thuật bên trong và loại bỏ nhu cầu lập trình viên phải tuân theo các thông số kỹ thuật một cách thủ công trong nhiều giờ. Tuy nhiên, nó không linh hoạt và không tính đến các tính năng nâng cao được nhúng trong các tiêu chuẩn. Do đó, đôi khi cần lập trình giao tiếp mạng ở cấp độ TCP, tức là ở cấp độ socket.
Socket có thể được xem như tương tự với một tệp trên đĩa: socket cũng được mô tả bởi một mô tả số nguyên mà qua đó dữ liệu có thể được đọc hoặc ghi, nhưng điều này xảy ra trong một cơ sở hạ tầng mạng phân tán. Không giống như tệp, số lượng socket trên một máy tính là có hạn, và do đó mô tả socket phải được yêu cầu từ hệ thống trước khi được liên kết với một tài nguyên mạng (địa chỉ, URL). Hãy nói trước rằng việc truy cập thông tin qua socket là dạng luồng, tức là không thể "tua lại" một "con trỏ" nào đó về đầu, như trong một tệp.
Luồng ghi và đọc không giao nhau nhưng có thể ảnh hưởng đến dữ liệu đọc hoặc ghi trong tương lai vì thông tin truyền đi thường được các máy chủ và chương trình máy khách diễn giải như các lệnh điều khiển. Các tiêu chuẩn giao thức xác định liệu một luồng có chứa lệnh hay dữ liệu.
Hàm SocketCreate
cho phép tạo một mô tả socket "trống" trong MQL5.
int SocketCreate(uint flags = 0)
Tham số duy nhất của nó được dành sẵn cho tương lai để chỉ định mẫu bit của các cờ xác định chế độ của socket, nhưng hiện tại chỉ hỗ trợ một cờ giả: SOCKET_DEFAULT tương ứng với chế độ hiện tại và có thể được bỏ qua. Ở cấp độ hệ thống, điều này tương đương với một socket ở chế độ chặn (điều này có thể khiến các lập trình viên mạng quan tâm).
Nếu thành công, hàm trả về tay cầm socket. Ngược lại, nó trả về INVALID_HANDLE.
Tối đa 128 socket có thể được tạo từ một chương trình MQL. Khi vượt quá giới hạn, lỗi 5271 (ERR_NETSOCKET_TOO_MANY_OPENED) được ghi vào _LastError
.
Sau khi đã mở socket, nó cần được liên kết với một địa chỉ mạng.
bool SocketConnect(int socket, const string server, uint port, uint timeout)
Hàm SocketConnect
thực hiện kết nối socket đến máy chủ tại địa chỉ và cổng được chỉ định (ví dụ, các máy chủ web thường chạy trên cổng 80 hoặc 443 cho HTTP và HTTPS, tương ứng, và SMTP trên cổng 25). Địa chỉ có thể là tên miền hoặc địa chỉ IP.
Tham số timeout
cho phép bạn đặt thời gian chờ tính bằng mili giây để đợi phản hồi từ máy chủ.
Hàm trả về dấu hiệu của kết nối thành công (true
) hoặc lỗi (false
). Mã lỗi được ghi vào _LastError
, ví dụ, 5272 (ERR_NETSOCKET_CANNOT_CONNECT).
Vui lòng lưu ý rằng địa chỉ kết nối phải được thêm vào danh sách các địa chỉ được phép trong cài đặt terminal (hộp thoại
Service
->Settings
->Advisors
).
Sau khi hoàn tất công việc với mạng, bạn nên giải phóng socket bằng SocketClose
.
bool SocketClose(const int socket)
Hàm SocketClose
đóng socket bằng tay cầm của nó, đã được mở trước đó bằng hàm SocketCreate
. Nếu socket trước đó đã được kết nối qua SocketConnect
, kết nối sẽ bị ngắt.
Hàm cũng trả về chỉ báo thành công (true
) hoặc lỗi (false
). Đặc biệt, khi truyền một tay cầm không hợp lệ vào _LastError
, lỗi 5270 (ERR_NETSOCKET_INVALIDHANDLE) được ghi lại.
Hãy nhắc lại rằng tất cả các hàm trong phần này và các phần tiếp theo đều bị cấm trong các chỉ báo: ở đó, nỗ lực làm việc với socket sẽ dẫn đến lỗi 4014 (ERR_FUNCTION_NOT_ALLOWED, "Hàm hệ thống không được phép gọi").
Hãy xem xét một ví dụ giới thiệu, script SocketConnect.mq5
. Trong các tham số đầu vào, bạn có thể chỉ định địa chỉ và cổng của máy chủ. Chúng ta dự định bắt đầu kiểm tra với các máy chủ web thông thường như mql5.com.
input string Server = "www.mql5.com";
input uint Port = 443;
2
Trong hàm OnStart
, chúng ta chỉ tạo một socket và liên kết nó với một tài nguyên mạng.
void OnStart()
{
PRTF(Server);
PRTF(Port);
const int socket = PRTF(SocketCreate());
if(PRTF(SocketConnect(socket, Server, Port, 5000)))
{
PRTF(SocketClose(socket));
}
}
2
3
4
5
6
7
8
9
10
Nếu tất cả các cài đặt trong terminal đều chính xác và nó được kết nối với Internet, chúng ta sẽ nhận được "báo cáo" sau.
Server=www.mql5.com / ok
Port=443 / ok
SocketCreate()=1 / ok
SocketConnect(socket,Server,Port,5000)=true / ok
SocketClose(socket)=true / ok
2
3
4
5