Mac Chat App, Not getting NSInputStream & NSOutputStream - python

I am working with a chat application with a simple python localhost server, using NSStream to send and recieve data via network socket connection. App just worked fine in the iPhone application, but not getting stream in the mac application.
My Python Server Code
from twisted.internet.protocol import Factory, Protocol
from twisted.internet import reactor
class MacChat(Protocol):
def connectionMade(self):
print "a client connected"
self.factory.clients.append(self)
print "clients are ", self.factory.clients
def connectionLost(self, reason):
self.factory.clients.remove(self)
def dataReceived(self, data):
a = data.split(':')
print a
if len(a) > 1:
command = a[0]
content = a[1]
msg = ""
if command == "iam":
self.name = content
msg = self.name + " has joined"
elif command == "msg":
msg = self.name + ": " + content
print msg
for c in self.factory.clients:
c.message(msg)
def message(self, message):
self.transport.write(message + '\n')
factory = Factory()
factory.clients = []
factory.protocol = MacChat
reactor.listenTCP(80, factory)
print "Mac Chat server started"
reactor.run()
Mac
ChatViewController.h
#import <Cocoa/Cocoa.h>
#interface ChatViewController : NSViewController
#property (strong,nonatomic) NSString *userName;
#end
ChatViewController.m
#import "ChatViewController.h"
#interface ChatViewController ()<NSTableViewDataSource,NSTableViewDelegate,NSStreamDelegate>
{
NSInputStream *inputStream;
NSOutputStream *outputStream;
NSMutableArray * messages;
}
#property (weak) IBOutlet NSButton *btnSend;
#property (weak) IBOutlet NSTextField *txtMessage;
#property (weak) IBOutlet NSTableView *tableview;
#end
#implementation ChatViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do view setup here.
}
-(void)setUserName:(NSString *)userName
{
[self initNetworkCommunication];
NSString *response = [NSString stringWithFormat:#"iam:%#",userName];
NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];
[outputStream write:[data bytes] maxLength:[data length]];
messages = [[NSMutableArray alloc] init];
}
- (void)initNetworkCommunication {
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)#"localhost", 80, &readStream, &writeStream);
inputStream = (__bridge_transfer NSInputStream *)readStream;
outputStream = (__bridge NSOutputStream *)writeStream;
inputStream.delegate=self;
outputStream.delegate=self;
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];
}
- (IBAction)btnAtnSend:(id)sender {
NSString *response = [NSString stringWithFormat:#"msg:%#", self.txtMessage.stringValue];
NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSASCIIStringEncoding]];
[outputStream write:[data bytes] maxLength:[data length]];
self.txtMessage.stringValue = #"";
}
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
// Get a new ViewCell
NSTableCellView *cellView = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self];
// Since this is a single-column table view, this would not be necessary.
// But it's a good practice to do it in order by remember it when a table is multicolumn.
if( [tableColumn.identifier isEqualToString:#"cell"] )
{
NSString *s = (NSString *) [messages objectAtIndex:row];
cellView.textField.stringValue = s;
}
return cellView;
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return [messages count];
}
-(CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row
{
return 30;
}
#pragma mark NSStream Delegate
-(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
switch (eventCode) {
case NSStreamEventOpenCompleted:
NSLog(#"Stream opened");
break;
case NSStreamEventHasBytesAvailable:
if (aStream == inputStream) {
uint8_t buffer[1024];
int len;
while ([inputStream hasBytesAvailable]) {
len = (int)[inputStream read:buffer maxLength:sizeof(buffer)];
if (len > 0) {
NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];
if (nil != output) {
NSLog(#"server said: %#", output);
[self messageReceived:output];
}
}
}
}
break;
case NSStreamEventErrorOccurred:
NSLog(#"Can not connect to the host!");
break;
case NSStreamEventEndEncountered:
{
[aStream close];
[aStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
break;
default:
NSLog(#"Unknown event");
}
}
- (void) messageReceived:(NSString *)message {
[messages addObject:message];
[self.tableview reloadData];
[self.tableview scrollRowToVisible:messages.count-1];
}
#end

OK. Looks like this is based on the example from raywenderlich.com.
The example is flawed, as mentioned by "glyph" in the comments section:
This tutorial makes some incorrect assumptions about how data is delivered to an application from a network.
Read glyph's post before building on this code.
For your particular problem, you've made a lot of changes to the original code. At a glance, it's not clear to me that "setUserName" is ever even called.
Without that, nothing else will happen.

Related

How to fix the connection problem between unity server and python client?

This is the error rising, could you please tell how shall I solve this issue?
I have unity side which is server and there is a server. There is also python side client, I just try to change the color of the sphere using control commands from python side
matlab/_controlUR_ver2/socket_client.py", line 9, in sendRandomColors
s.connect(('192.168.43.18', 1755))
TimeoutError: [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
This is the python client:
import socket
import random
from time import sleep
def sendRandomColors():
s = socket.socket()
# connect to the server on local computer
s.connect(('192.168.43.18', 1755))
s.send((
str(random.randint(0,255)) + ","+
str(random.randint(0,255)) + ","+
str(random.randint(0,255)) + ","+
str(random.randint(0,255))).encode())
s.close()
for i in range(100):
sendRandomColors()
sleep(1)
and This is the c# server on unity:
using System;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
public class ChangeColor : MonoBehaviour
{
static Socket listener;
private CancellationTokenSource source;
public ManualResetEvent allDone;
public Renderer objectRenderer;
private Color matColor;
public static readonly int PORT = 1755;
public static readonly int WAITTIME = 1;
ChangeColor()
{
source = new CancellationTokenSource();
allDone = new ManualResetEvent(false);
}
// Start is called before the first frame update
async void Start()
{
objectRenderer = GetComponent<Renderer>();
await Task.Run(() => ListenEvents(source.Token));
}
// Update is called once per frame
void Update()
{
objectRenderer.material.color = matColor;
}
private void ListenEvents(CancellationToken token)
{
IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork);
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, PORT);
listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(localEndPoint);
listener.Listen(10);
while (!token.IsCancellationRequested)
{
allDone.Reset();
print("Waiting for a connection... host :" + ipAddress.MapToIPv4().ToString() + " port : " + PORT);
listener.BeginAccept(new AsyncCallback(AcceptCallback),listener);
while(!token.IsCancellationRequested)
{
if (allDone.WaitOne(WAITTIME))
{
break;
}
}
}
}
catch (Exception e)
{
print(e.ToString());
}
}
void AcceptCallback(IAsyncResult ar)
{
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
allDone.Set();
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
}
void ReadCallback(IAsyncResult ar)
{
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
int read = handler.EndReceive(ar);
if (read > 0)
{
state.colorCode.Append(Encoding.ASCII.GetString(state.buffer, 0, read));
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
}
else
{
if (state.colorCode.Length > 1)
{
string content = state.colorCode.ToString();
print($"Read {content.Length} bytes from socket.\n Data : {content}");
SetColors(content);
}
handler.Close();
}
}
//Set color to the Material
private void SetColors (string data)
{
string[] colors = data.Split(',');
matColor = new Color()
{
r = float.Parse(colors[0]) / 255.0f,
g = float.Parse(colors[1]) / 255.0f,
b = float.Parse(colors[2]) / 255.0f,
a = float.Parse(colors[3]) / 255.0f
};
}
private void OnDestroy()
{
source.Cancel();
}
public class StateObject
{
public Socket workSocket = null;
public const int BufferSize = 1024;
public byte[] buffer = new byte[BufferSize];
public StringBuilder colorCode = new StringBuilder();
}
}

How to change ROS Package to subscribe to general IMU message instead of custom one?

I have created a ROS package that use custom IMU messages. Instead of that I would like to change the implementation to fit sensor_msgs/msg/imu instead of custom one. So first I found the nodes inside the package that subscribe to that custom IMU message. This is that node.
#!/usr/bin/python3
import numpy as np
from node_registry.decorators import rosnode, register
from driver_ros_msgs.msg import GImu as Imu
from deepx_ros_common.coordinate_converter import quaternion2rpy
_sub_topic = "/backhoe/imu"
_qos = 1
#rosnode.parameter("period", 0.025)
#rosnode
def node_name():
return "test_imu"
#rosnode.inject
def yaw_deg():
return 0
#rosnode.subscribe(Imu, _sub_topic, _qos)
def subscrbe_cb(msg):
orientation = msg.imu.orientation
ypr_rad = quaternion2rpy(
[orientation.w, orientation.x, orientation.y, orientation.z])[0]
rosnode.logger.info(f"Output ypr: {np.rad2deg(ypr_rad)}")
register()
So is it enough just to change the line _sub_topic = "/backhoe/imu" into _sub_topic = "/sensor_msgs/msg/imu" or need something more in this node? Also I have IMU driver cpp code like this
#include <tf2/LinearMath/Quaternion.h>
#include <string>
#include <memory>
#include "vectornav_driver/imu_driver.hpp"
namespace vectornav_driver
{
ImuDriver::ImuDriver(
const std::string node_name, const rclcpp::NodeOptions & options)
: Node(node_name, options),
header_('$'),
delim_("\r\n"),
status_start_(26),
status_end_(30),
yaw_start_(31),
yaw_end_(39),
pitch_start_(40),
pitch_end_(48),
roll_start_(49),
roll_end_(57)
{
}
ImuDriver::~ImuDriver()
{
}
void ImuDriver::init()
{
rclcpp::Parameter frame_id;
rclcpp::Parameter ip;
rclcpp::Parameter port;
auto flag_frame_id = get_parameter_or(
"frame_id", frame_id,
rclcpp::Parameter("frame_id", "default_link"));
if (!flag_frame_id) {
RCLCPP_WARN_ONCE(
get_logger(),
"Could not get frame_id, setting: %s",
frame_id.as_string().c_str());
}
frame_id_ = frame_id.as_string();
auto flag_ip = get_parameter_or(
"ip", ip,
rclcpp::Parameter("ip", "192.168.255.1"));
if (!flag_ip) {
RCLCPP_WARN_ONCE(
get_logger(),
"Could not get ip, setting: %s",
ip.as_string().c_str());
}
auto flag_port = get_parameter_or(
"port", port,
rclcpp::Parameter("port", 10003));
if (!flag_port) {
RCLCPP_WARN_ONCE(
get_logger(),
"Could not get port, setting: %d",
port.as_int());
}
auto hardware_id = ip.as_string() + ":" + std::to_string(port.as_int());
rclcpp::Parameter buffer_limit;
auto flag_buffer_limit = get_parameter_or(
"buffer_limit", buffer_limit,
rclcpp::Parameter("buffer_limit", 143));
if (!flag_buffer_limit) {
RCLCPP_WARN_ONCE(
get_logger(),
"Could not get buffer_limit, setting: %d",
buffer_limit.as_int());
}
buffer_limit_ = buffer_limit.as_int();
rclcpp::Parameter diagnostics_enable;
auto flag_diag_enable = get_parameter_or(
"diagnostics.enable",
diagnostics_enable,
rclcpp::Parameter("diagnostics.enable", false));
if (!flag_diag_enable) {
RCLCPP_WARN_ONCE(
get_logger(),
"Could not get diagnostics.enable, setting: %d",
diagnostics_enable.as_bool());
}
rclcpp::Parameter min_freq;
auto flag_min_freq = get_parameter_or(
"diagnostics.min_freq",
min_freq,
rclcpp::Parameter("diagnostics.min_freq", 40.0));
if (!flag_min_freq) {
RCLCPP_WARN_ONCE(
get_logger(),
"Could not get min_freq, setting: %f",
min_freq.as_double());
}
rclcpp::Parameter max_freq;
auto flag_max_freq = get_parameter_or(
"diagnostics.max_freq",
max_freq,
rclcpp::Parameter("diagnostics.max_freq", 45.0));
if (!flag_max_freq) {
RCLCPP_WARN_ONCE(
get_logger(),
"Could not get max_freq, setting: %f",
max_freq.as_double());
}
rclcpp::Parameter period;
auto flag_period = get_parameter_or(
"diagnostics.period",
period,
rclcpp::Parameter("diagnostics.period", 1.0));
if (!flag_period) {
RCLCPP_WARN_ONCE(
get_logger(),
"Could not get period, setting: %f",
period.as_double());
}
if (diagnostics_enable.as_bool()) {
min_freq_ = min_freq.as_double();
max_freq_ = max_freq.as_double();
auto freq_param = diagnostic_updater::FrequencyStatusParam(
&min_freq_,
&max_freq_);
freq_status_ = std::make_shared<
diagnostic_updater::FrequencyStatus>(freq_param);
sensor_status_ = std::make_shared<
SensorStatus>();
updater_ = std::make_unique<diagnostic_updater::Updater>(
this, period.as_double());
updater_->add(*freq_status_);
updater_->add(*sensor_status_);
updater_->setHardwareID(hardware_id);
}
rclcpp::Parameter is_unittest;
auto flag_is_unittest = get_parameter_or(
"is_unittest",
is_unittest,
rclcpp::Parameter("is_unittest", false));
if (!flag_is_unittest) {
RCLCPP_WARN_ONCE(
get_logger(),
"Could not get is_unittest, setting: %d",
is_unittest.as_bool());
}
tcp_ = std::make_unique<driver_common_utils::TcpIO>(
ip.as_string(), port.as_int());
if (is_unittest.as_bool()) {
rclcpp::Rate rate(5.0);
rate.sleep();
}
auto flag_init = tcp_->init();
if (flag_init) {
rclcpp::QoS qos(rclcpp::KeepLast(1));
pub_imu_ = create_publisher<GImu>("imu", qos);
boost::asio::async_read_until(
tcp_->getSocket(),
boost::asio::dynamic_buffer(buffer_),
delim_,
boost::bind(
&ImuDriver::receiveHandler,
this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
tcp_->run();
} else {
RCLCPP_ERROR_ONCE(get_logger(), "Socket init error");
}
}
void ImuDriver::receiveHandler(
const boost::system::error_code & error, std::size_t bytes_transferred)
{
if (rclcpp::ok()) {
if ((!error.failed() || error == boost::asio::error::message_size)) {
if (buffer_.size() > buffer_limit_) {
buffer_.clear();
}
if (bytes_transferred && buffer_.size()) {
freq_status_->tick();
auto buffer = buffer_.substr(0, bytes_transferred);
auto get_header = buffer.at(0);
if (get_header == header_) {
auto status = decode<uint16_t>(
buffer, status_start_, status_end_, true);
auto yaw = toRadian(
decode<float>(
buffer, yaw_start_, yaw_end_));
auto pitch = toRadian(
decode<float>(
buffer, pitch_start_, pitch_end_));
auto roll = toRadian(
decode<float>(
buffer, roll_start_, roll_end_));
tf2::Quaternion quaternion;
quaternion.setRPY(roll, pitch, yaw);
GImu gimu;
gimu.header.frame_id = frame_id_;
gimu.header.stamp = get_clock()->now();
auto mode_bit_1 = boolBitValue(status, 0);
auto mode_bit_2 = boolBitValue(status, 1);
gimu.mode = (mode_bit_1 * 1) + (mode_bit_2 * 2);
gimu.gnss_fix = boolBitValue(status, 2);
gimu.imu_error = boolBitValue(status, 4);
gimu.magnetometer_pressure_error = boolBitValue(status, 5);
gimu.gnss_error = boolBitValue(status, 6);
gimu.gnss_heading_ins = boolBitValue(status, 8);
gimu.gnss_compass = boolBitValue(status, 9);
gimu.imu.orientation.w = quaternion.getW();
gimu.imu.orientation.x = quaternion.getX();
gimu.imu.orientation.y = quaternion.getY();
gimu.imu.orientation.z = quaternion.getZ();
sensor_status_->sensorStatus(
gimu.mode,
gimu.gnss_fix,
gimu.imu_error,
gimu.magnetometer_pressure_error,
gimu.gnss_error);
pub_imu_->publish(gimu);
}
buffer_.erase(0, bytes_transferred);
}
boost::asio::async_read_until(
tcp_->getSocket(),
boost::asio::dynamic_buffer(buffer_),
delim_,
boost::bind(
&ImuDriver::receiveHandler,
this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
} else {
RCLCPP_ERROR(
get_logger(),
"Receive handler error: %s", error.message().c_str());
}
} else {
RCLCPP_INFO(get_logger(), "Receive handler: node shutdown called");
}
}
} // namespace vectornav_driver
so should be done any changes in the driver too?
Thanks

Why I get a error 200 by websocket with python?

Code:
const WebSocket = require('ws');
const shaUtil = require('js-sha256');
String.prototype.hashCode = function() {
return shaUtil(String(this));
};
const server = new WebSocket.Server({port:2909}); // Change to another port if you like.
// Hashes of client keys. Generate them using getHash.js and place them here.
const passes = {
'86cec081a5288000ddb804c24ac70de62a5060e5b4f4068b01a01f9f29dddacc': 0, // Receiver's key.
'c01223ad2ba8cdd184ded788cf6d3469111229cbe6cb3939ce24f471e8f257ca': 1, // Buzzer #1's key.
'5476be1700a54be0572b0066b32b5905986641fa163c5eabd52369eb3a2685cf': 2 // Buzzer #2's key...
};
var receiver = null;
var senders = {1: null, 2: null, 3: null, 4: null}; // You can add more/remove buzzers if you want to.
const lockClients = true; // If it is true, a connected client will not be overriden by another client logging in until it disconnects.
if (lockClients) canConnect = function(id) {
if (id == 0) return receiver === null;
return senders[id] === null;
}
else canConnect = function(id) {
return true;
}
function processBuzzer(client) {
if (receiver == null) return;
receiver.send('BUZZER '+client.buzzerId);
//console.log('Buzzer #'+client.buzzerId+' is activated.');
}
function onDisconnect(id) {
if (id === 0) {
receiver = null;
console.log('Receiver has disconnected.');
} else {
senders[id] = null;
console.log('Sender #' + id + ' has disconnected.');
}
}
server.on('connection', function(client) {
client.sendBuzzer = function() {};
client.on('message', function(message) {
if (message.startsWith('PASSWORD: ')) {
let id = passes[message.substring(10).hashCode()];
if (id !== undefined && canConnect(id)) {
if (client.buzzerId !== undefined) onDisconnect(client.buzzerId);
client.buzzerId = id;
if (id === 0) {
receiver = client;
console.log('Receiver has connected.');
} else {
senders[id] = client;
console.log('Sender #' + id + ' has connected.');
client.sendBuzzer = function() { processBuzzer(this) };
client.send('CONNECTED SUCCESSFULLY');
}
}
}
if (message == 'BUZZER') client.sendBuzzer();
});
client.on('close', function() {
if (client.buzzerId !== undefined) onDisconnect(client.buzzerId);
});
});
console.log('Server is running.');
If i started this with nodeJS with "node server.js", it appears Server is running.....no mistakes.....and now, Iwill connect to this server with the receiver.py (Python-File):
serverAddress = 'ws://192.168.1.50:2909' # The server's address.
clientKey = 'receiver' # The client key corresponding to the receiver's hash.
buzzerSoundFile = 'buzzer.wav' # The name/path of the buzzer sound file.
import asyncio
import websockets
from win32com.client import Dispatch
import winsound
from threading import Thread
app = Dispatch('Powerpoint.Application')
def playBuzzerSound():
global buzzerSoundFile
winsound.PlaySound(buzzerSoundFile, winsound.SND_FILENAME+winsound.SND_ASYNC)
async def mainFunction():
global serverAddress, clientKey
async with websockets.connect(serverAddress) as ws:
await ws.send('PASSWORD: ' + clientKey)
while True:
msg = await ws.recv()
if msg.startswith('BUZZER '):
if app.Run('onBuzzerActivated', int(msg[7:])):
Thread(target=playBuzzerSound).start();
asyncio.get_event_loop().run_until_complete(mainFunction())
I got an error 200 like this:
websockets.exceptions.InvalidStatusCode: server rejected WebSocket connection: HTTP 200
What's wrong ??

Frida - hook native method failure on android-Q

I have a sample app, which have a int add(int a,int b) in native library.
I use below code to hook the add method:
#!/usr/bin/env python3
import frida
import sys
package_name = "com.sample.hello"
apiname = "add"
def get_messages_from_js(message, data):
if message['type'] == 'send':
print(message['payload'])
else:
print(message)
def instrument_debugger_checks():
hook_code = """
Interceptor.attach(Module.findExportByName(null, "%s"), {
onEnter: function(args) {
console.log("onEnter...");
//send (Memory.readUtf8String (args [1]));
},
onLeave: function(args) {
console.log("onLeave...");
}
});
"""%(apiname)
return hook_code
process = frida.get_usb_device().attach(package_name)
script = process.create_script(instrument_debugger_checks())
script.on('message',get_messages_from_js)
script.load()
sys.stdin.read()
I use below command to get the function name from so:
$ nm -D libnative2.so |grep add
0000000000082504 T _ZNSt6__ndk114__shared_count12__add_sharedEv
0000000000082574 T _ZNSt6__ndk119__shared_weak_count10__add_weakEv
000000000008255c T _ZNSt6__ndk119__shared_weak_count12__add_sharedEv
0000000000042d8c T add
I have tried all these names, result is the same.
But when I run it, I got below error:
{'type': 'error', 'description': 'Error: expected a pointer', 'stack': 'Error: expected a pointer\n at frida/runtime/core.js:387\n at /script1.js:9', 'fileName': 'frida/runtime/core.js', 'lineNumber': 387, 'columnNumber': 1}
What's wrong with my code?
Looks like You have an issue with timing.
Try the following Frida script:
Java.perform(function() {
const System = Java.use("java.lang.System");
const Runtime = Java.use("java.lang.Runtime");
const SystemLoad_2 = System.loadLibrary.overload("java.lang.String");
const VMStack = Java.use("dalvik.system.VMStack");
SystemLoad_2.implementation = function(library) {
console.log("Loading dynamic library => " + library);
try {
const loaded = Runtime.getRuntime().loadLibrary0(VMStack.getCallingClassLoader(), library);
if(library.includes("native2")) {
// here your hook
Interceptor.attach(Module.findExportByName("libnative2.so", "%s"), {
onEnter: function(args) {
console.log("onEnter...");
//send (Memory.readUtf8String (args [1]));
},
onLeave: function(args) {
console.log("onLeave...");
}
});
}
return loaded;
} catch(ex) {
console.log(ex);
}
};
});

How to send data from MQL4 into Socket

Now, I trying to send the real-time data from MQL4. Into the socket server build by Python-Flask
My MQL4 using socket-library-mt4-mt5.mqh. But i don't how to handle the event to the socket.
My socket server
from flask import Flask, render_template
from flask_socketio import SocketIO
app = Flask(__name__)
socketio = SocketIO(app)
#app.route('/')
def sessions():
return render_template('index.html')
def messageReceived(methods=['GET', 'POST']):
print('message was received!!!')
#socketio.on('my event')
def handle_my_custom_event(json, methods=['GET', 'POST']):
print('received my event: ' + str(json))
socketio.emit('my response', json, callback = messageReceived)
My MQL4 code, As Socket client
#define SOCKET_LIBRARY_USE_EVENTS
#include <socket-library-mt4-mt5.mqh>
string Hostname = "127.0.0.1";
ushort ServerPort = "5000";
ClientSocket * glbClientSocket = NULL;
int OnInit()
{
return NULL;
}
void OnDeinit(const int reason)
{
if (glbClientSocket) {
delete glbClientSocket;
glbClientSocket = NULL;
}
}
void OnTick()
{
if (!glbClientSocket) {
glbClientSocket = new ClientSocket(Hostname, ServerPort);
if (glbClientSocket.IsSocketConnected()) {
Print("Client connection succeeded");
} else {
Print("Client connection failed");
}
}
if (glbClientSocket.IsSocketConnected()) {
string strMsg = Symbol() + "," + DoubleToString(SymbolInfoDouble(Symbol(), SYMBOL_BID), 6) + "," + DoubleToString(SymbolInfoDouble(Symbol(), SYMBOL_ASK), 6) + " Hello from MQL \n";
glbClientSocket.Send(strMsg);
} else {
}
if (!glbClientSocket.IsSocketConnected()) {
// Destroy the server socket. A new connection
// will be attempted on the next tick
Print("Client disconnected. Will retry.");
delete glbClientSocket;
glbClientSocket = NULL;
}
}
And i check The connection it's work, But still wrong the method
As you see the my MQL4 code it's doesn't have the handle event function
127.0.0.1 - - [2019-08-29 13:25:36] "AUDUSD,0.672250,0.672360 Hello from MQL" 400 - 0.000403
<socket fileno=10 sock=127.0.0.1:5000 peer=127.0.0.1:37348>: Invalid HTTP method: 'AUDUSD,0.672260,0.672360 Hello from MQL \n'
The question is how to handle event like socket.on('my event') in javascript. Into my MQL4 code.

Categories

Resources