I have created a socket file something like the following and want that the output of the socket must be read by the MQL5. See the following Python code:
daemon.py
import socket
#import arcpy
def actual_work():
#val = arcpy.GetCellValue_management("D:\dem-merged\lidar_wsg84", "-95.090174910630012 29.973962146120652", "")
#return str(val)
return 'dummy_reply'
def main():
sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
try:
sock.bind( ('127.0.0.1', 6666) )
while True:
data, addr = sock.recvfrom( 4096 )
reply = actual_work()
sock.sendto(reply, addr)
except KeyboardInterrupt:
pass
finally:
sock.close()
if __name__ == '__main__':
main()
client.py
import socket
import sys
def main():
sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
sock.settimeout(1)
try:
sock.sendto('', ('127.0.0.1', 6666))
reply, _ = sock.recvfrom(4096)
print reply
except socket.timeout:
sys.exit(1)
finally:
sock.close()
if __name__ == '__main__':
main()
Kindly, help me in accepting the output of the socket through MQL5
EDITED
I just want that the reply should be accepted on the MQL5 in a variable, which produced by the daemon.py. How I can do that? Say I want that MQL5 should print the response from the Python , as in the above example, I want that MQL5 should give output as dummy_reply in string variable if possible.
Is there any possibility with ZeroMQ?
I want to get the client.py to be done with MQL5 instead of using Python. Please help me.
Please find a running example. Important element is to create byte object of the payload instead of string before you send as reply. socket object produces and ingests only bytes
import socket
import threading
import sys
def actual_work(data):
print(data)
return b'ACK'
def daemon():
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('127.0.0.1', 6666))
print("Listening on udp %s:%i" % ('127.0.0.1', 6666))
try:
while True:
data, addr = sock.recvfrom(4096)
ack = actual_work(data)
sock.sendto(ack, addr)
except Exception as e:
print(e)
finally:
sock.close()
def client():
sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
sock.settimeout(1)
try:
sock.sendto(b'payload', ('127.0.0.1', 6666))
reply, _ = sock.recvfrom(4096)
print(reply)
except socket.timeout as e:
print(e)
sys.exit(1)
finally:
sock.close()
if __name__ == '__main__':
thread = threading.Thread(target=daemon)
thread.start()
client()
client()
client()
client()
#Issue kill thread here
thread.join()
Related
I'm trying to run a client/server script, where the client sends a file to the server and waits for responses until the server sends a stop message.
The problem is: once the connection is established the client starts sending data but until I press CTRL-C the server cannot recreate the file. Only after CTRL-C print "file is fully created" and the file becomes visible, instead, before it's seems to be waiting for something. idk where the problem is. Also tried changing condition on send loop using len(), but doesn't work. Anyone know how to fix it ?
client.py :
import socket # Import socket module
# from threading import Thread
s = socket.socket() # Create a socket object
HOST = "101.xx.x.xxx" # public IP address
PORT = 4243 # Reserve a port for your service.
PDF_PATH = "exam.pdf"
s.connect((HOST, PORT))
def send():
f = open(PDF_PATH, "rb")
while data := f.read(4096):
s.send(data)
f.close()
return
def receive():
while 1:
exercise = s.recv(4096)
if exercise == "stop!":
s.close()
break
f = open(f"{exercise}.txt", "wb")
while data := f.read(4096):
f.write(data)
return
def main():
send()
receive()
if __name__ == "__main__":
main()
server.py :
import socket
from threading import Thread
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
HOST = socket.gethostname()
IP = socket.gethostbyname(HOST)
PORT = 4243
s.bind(('', PORT))
s.listen(5)
def receive_file(conn, i):
f = open(f"exam.pdf", "wb")
while received := conn.recv(4096):
f.write(received)
print("File is fully copied\n")
f.close()
def send_result(conn,i):
while 1:
nbr = str(input("which exercise? "))
if nbr == "stop!":
break
f = open(f"exercise{nbr}.txt", "rb")
conn.send(bytes(f"exercise{nbr}.txt", encoding="utf-8"))
while data := f.read(4096):
conn.send(data)
f.close()
def main():
try:
while 1:
i = 0
conn, addr = s.accept()
print("Got connection from", addr)
# c.send(b"Thank you for connecting")
t = Thread(target=receive_file, args=(conn, i))
t.start()
t.join()
t = Thread(target=send_result, args=(conn, i))
t.start()
t.join()
except KeyboardInterrupt:
print("interrupting \n")
conn.close()
s.close()
if _name_ == '_main_':
main()
conn.recv() in the server won't return '' (no more data) unless the client closes the connection or calls shutdown(SHUT_WR) to indicate sends are complete:
def send():
with open(PDF_PATH, "rb") as f:
while data := f.read(4096):
s.sendall(data)
s.shutdown(socket.SHUT_WR)
An alternative is to design a protocol that sends the length of data before the data so you know when you've received the complete transmission. This would be required if you need to send more than one thing without closing the socket or shutting down sends. You're going to need this to make the receive portion of the server work if you want to send more than one exercise file.
Refer to this answer for an example of sending multiple files over a socket.
For some reason, the next elementary program connects the client to the server only from the second time. And so every time after restarting the server. Can someone explain the reason for this behavior and how to solve this problem? Maybe it's because asyncore is only used on the server side? (Windows 7, Python 3) Thank you in advance!
Сlient:
import socket
sock = socket.socket()
host = 'localhost'
port = 8081
tempr = port
sock.connect((host,port))
Server:
import asyncore
import socket
import time
class EchoHandler(asyncore.dispatcher_with_send):
def handle_read(self):
data = self.recv(1024)
class EchoServer(asyncore.dispatcher):
def __init__(self, host, port):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind((host, port))
self.listen(2)
def handle_accept(self):
pair = self.accept()
if pair is not None:
sock, addr = pair
print ('Incoming connection from %s' % repr(addr))
handler = EchoHandler(sock)
def main():
host = 'localhost'
port = 8081
server = EchoServer(host, port)
print ('Server %s running'% port)
asyncore.loop()
if __name__ == '__main__':
main()
The whole point of socket is to send() and recv() (receive) data between client and server. You must send some data (even an empty string must be sent) to server after connecting to server and server may return some data to client and/or just close connection.
my_client.py
import socket
sock = socket.socket()
sock.connect(('localhost', 8081))
sock.send(b'data from client')
print(sock.recv(32))
sock.close()
my_server.py
import asyncore
import socket
import time
class EchoHandler(asyncore.dispatcher_with_send):
def handle_read(self):
data = self.recv(1024)
print('data from client', data)
self.send(b'data from server')
self.close()
class EchoServer(asyncore.dispatcher):
def __init__(self, host, port):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind((host, port))
self.listen(2)
def handle_accept(self):
pair = self.accept()
if pair is not None:
sock, addr = pair
print('Incoming connection from %s' % repr(addr))
handler = EchoHandler(sock)
def main():
host = 'localhost'
port = 8081
server = EchoServer(host, port)
print('Server %s running' % port)
asyncore.loop()
if __name__ == '__main__':
main()
Update:
You do get an error: OSError: [WinError 10038] because you are closing socket in server without reading all data from client. The same is happening in client side too.
In Python documentation it is explicitly stated that these are very basic examples.
Use method sendall() to be sure that all data is sent. Method send() does not guaranty sending of all data.
You must read data from socket with a while loop like this:
my_client.py
import socket
sock = socket.socket()
sock.connect(('localhost', 8081))
sock.sendall(b'data from client')
chunk = b'' # socket.recv returns bytes
data = b'' # defined before to avoid NameError
while True:
chunk = sock.recv(32)
if chunk:
data += chunk
else:
break
print(data)
sock.close()
my_server.py
import asyncore
import socket
import time
class EchoHandler(asyncore.dispatcher_with_send):
def handle_read(self):
chunk = b'' # socket.recv returns bytes
data = b'' # defined before to avoid NameError
while True:
chunk = self.recv(1024)
if chunk:
data += chunk
else:
break
print('data from client', data)
self.sendall(b'data from server')
self.close()
class EchoServer(asyncore.dispatcher):
def __init__(self, host, port):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind((host, port))
self.listen(2)
def handle_accept(self):
pair = self.accept()
if pair is not None:
sock, addr = pair
print('Incoming connection from %s' % repr(addr))
handler = EchoHandler(sock)
def main():
host = 'localhost'
port = 8081
server = EchoServer(host, port)
print('Server %s running' % port)
asyncore.loop()
if __name__ == '__main__':
main()
I am new to python and i am trying to make a multithreded tcp server and client to be able to send files between them. I did write some simple codes for these two programs but every time I get empty file on server's site. The file does create in the folder but when I open it it is blank inside. I also tried to send .png files but windows photoviewer doesn't open them saying they are empty. I didn't find anyone encourting such problem so that's why i am asking
Client.py
import socket # Import socket module
HOST = "localhost" # Host address / name
PORT = 2137 # Reserves port for the service
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((HOST, PORT))
fileToSend = open('test.txt', 'rb')
print "File ready to be sent"
l = fileToSend.read(1024)
while l:
print "Sending the file"
client.send(l)
l = fileToSend.read(1024)
fileToSend.close() print "done"
client.close()
Server.py
import socket
from threading import Thread
from SocketServer import ThreadingMixIn
import sys
TCPHOST = "localhost"
TCPPORT = 2137
BUFFER_SIZE = 20
class ClientThread(Thread):
def __init__(self, HOST, PORT):
Thread.__init__(self)
self.HOST = HOST
self.PORT = PORT
print "New thread started for " + HOST + " on port " + str(PORT)
def run(self):
f = open('received.py', 'wb')
while True:
try:
data = conn.recv(1024)
except socket.error, e:
print "Error receiving data: %s" % e
sys.exit(1)
while data:
print "Receiving"
f.write(data)
data = conn.recv(1024)
f.close()
try:
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((TCPHOST, TCPPORT))
print "Socket created"
except socket.error, err:
print "Failed to create socket" % err
threads = []
while True:
server.listen(4)
print "Waiting for connections"
(conn, (HOST, PORT)) = server.accept()
thread = ClientThread(HOST, PORT)
thread.start()
threads.append(thread)
for t in threads:
t.join()
I am not sure what you actually want to do, because I see that you import SocketServer however you are not using it all.
If you are trying to run a simple socket server then the class ClientThread and all the other stuff about threads in that file are not necessary.
The following code in server.py will do the job
import socket
import sys
TCPHOST = "localhost"
TCPPORT = 2137
BUFFER_SIZE = 20
try:
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((TCPHOST, TCPPORT))
server.listen(4)
print "Socket created"
except socket.error, err:
print "Failed to create socket" % err
while True:
print "Waiting for connections"
(conn, (TCPHOST, TCPPORT)) = server.accept()
try:
while True:
data = conn.recv(1024)
f = open('received.py', 'wb')
if data:
print "Receiving " + data
f.write(data)
else:
f.close()
break;
except socket.error, e:
#pass
print "Error receiving data: %s" % e
#sys.exit(1)
finally:
conn.close()
However if you are trying to implement a threaded TCPServer using the ThreadingMixIn then you need to create a class that subclasses SocketServer and override its handle() function
Python documentation is quite helpful on this
https://docs.python.org/3.5/library/socketserver.html
(ThreadingMixin is at the bottom of the page)
i'm just started to learn Python, and i can't implement a good solution.
I want to write a client/server which allows you to send messages (like: texted, entered, texted, entered) on server until you press Ctrl+C interruption, and this int should close the socket both on server and client.
My very basic and, i suppose, very common client/server example on Python, but as you know - this pair is for single shot, and program is closing.
client.py
import socket
TCP_IP = '127.0.0.1'
TCP_PORT = 5005
BUFFERSIZE = 1024
sock = socket.socket()
sock.connect((TCP_IP, TCP_PORT))
msg = input('Enter your text: ')
sock.send(msg.encode())
data = sock.recv(BUFFERSIZE).decode()
sock.close()
print('Recieved data: ',data)
server.py
import socket
import sys
TCP_IP = '127.0.0.1'
TCP_PORT = 5005
BUFFER_SIZE = 1024
sock = socket.socket()
sock.bind((TCP_IP, TCP_PORT))
sock.listen(1)
conn, addr = sock.accept()
print('Connection address:\nIP:',addr[0])
print('Port:',addr[1])
while 1:
data = conn.recv(BUFFER_SIZE)
if not data: break
msg = data.decode()
print('Recieved data: ', msg)
conn.send(data)
conn.close()
Any suggestions?
Add a try...finally to the bottom part like so:
try:
while 1:
data = conn.recv(BUFFER_SIZE)
if not data: break
msg = data.decode()
print('Recieved data: ', msg)
conn.send(data)
finally:
conn.close()
Ctrl+C raises KeyboardInterrupt exception. When it does, the finally will be called, and safely close the socket.
The same can be done to the client in order to close it client-side:
try:
msg = input('Enter your text: ')
sock.send(msg.encode())
data = sock.recv(BUFFERSIZE).decode()
finally:
sock.close()
from socket import socket, AF_INET, SOCK_STREAM
sock = socket(AF_INET, SOCK_STREAM)
sock.bind(("localhost", 7777))
sock.listen(1)
while True:
try:
connection, address = sock.accept()
print("connected from " + address)
received_message = sock.recv(300)
if not received_message:
break
connection.sendall(b"hello")
except KeyBoardInterrupt:
connection.close()
so Im trying to wrap my head around sockets and have this pretty simple script
but for some reason I can't kill this script with a KeyboardInterrupt
how do I do kill the script with a KeyboardInterrupt that and why can't I kill it with a KeyboardInterrupt?
To break to get out the while loop. Without break, the loop will not end.
To be safe, check whether connection is set.
from socket import socket, AF_INET, SOCK_STREAM
sock = socket(AF_INET, SOCK_STREAM)
sock.bind(("localhost", 7777))
sock.listen(1)
while True:
connection = None # <---
try:
connection, address = sock.accept()
print("connected from ", address)
received_message = connection.recv(300)
if not received_message:
break
connection.sendall(b"hello")
except KeyboardInterrupt:
if connection: # <---
connection.close()
break # <---
UPDATE
There was a typo: KeyBoardInterrupt should be KeyboardInterrupt.
sock.recv should be connection.recv.
Try to use timeout to make the program periodically "jumps out" from the accept waiting process to receive KeyboardInterrupt command.
Here is an example of socket server:
import socket
host = "127.0.0.1"
port = 23333
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((host,port))
sock.listen()
sock.settimeout(0.5)
print("> Listening {}:{} ...".format(host,port))
try:
while True:
try:
conn, addr = sock.accept()
data = conn.recv(1024)
if not data:
print("x Client disconnected!")
# break
else:
print("> Message from client: {}".format(data.decode()))
msg = "> Message from server".format(data.decode()).encode()
conn.sendall(msg)
except socket.timeout:
# print("Timeout")
pass
except KeyboardInterrupt:
pass
except KeyboardInterrupt:
print("Server closed with KeyboardInterrupt!")
sock.close()
Try adding a timeout to the socket, like so:
from socket import socket, AF_INET, SOCK_STREAM
sock = socket(AF_INET, SOCK_STREAM)
sock.bind(("localhost", 7777))
sock.settimeout(1.0)
sock.listen(1)
while True:
try:
connection, address = sock.accept()
print("connected from " + address)
received_message = sock.recv(300)
if not received_message:
break
connection.sendall(b"hello")
except IOError as msg:
print(msg)
continue
except KeyboardInterrupt:
try:
if connection:
connection.close()
except: pass
break
sock.shutdown
sock.close()
I had this issue on Windows. Here's how I handle stopping the process:
try:
while self.running:
try:
c, addr = self.socket.accept()
print("Connection accepted from " + repr(addr[1]))
# do special stuff here...
print("sending...")
continue
except (SystemExit, KeyboardInterrupt):
print("Exiting....")
service.stop_service()
break
except Exception as ex:
print("======> Fatal Error....\n" + str(ex))
print(traceback.format_exc())
self.running = False
service.stop_service()
raise
except (SystemExit, KeyboardInterrupt):
print("Force Exiting....")
service.stop_service()
raise
def stop_service(self):
"""
properly kills the process: https://stackoverflow.com/a/16736227/4225229
"""
self.running = False
socket.socket(socket.AF_INET,
socket.SOCK_STREAM).connect((self.hostname, self.port))
self.socket.close()
Note that in order to trigger a KeyboardInterrupt exception, use:
Ctrl+Fn+PageUp(Pause/Break)
The CTRL+C event can be caught in a separate process and sent back to another thread running in the main process to kill the socket. Example below, tested successfully on Windows 10 with Python 3.5.4. Placed some comments and print statements around so you can see what's happening.
from multiprocessing import Pipe, Process
from socket import socket, AF_INET, SOCK_STREAM
from threading import Thread
import time
def detect_interrupt(conn):
try:
print("Listening for KeyboardInterrupt...")
while True:
time.sleep(1)
except KeyboardInterrupt:
print("Detected KeyboardInterrupt!")
print("Sending IPC...")
conn.send(True)
conn.close()
def listen_for_interrupt(conn, sock):
print("Listening for IPC...")
conn.recv()
print("Detected IPC!")
print("Closing sock...")
sock.close()
if __name__ == "__main__":
sock = socket(AF_INET, SOCK_STREAM)
sock.bind(("localhost", 7777))
sock.listen(1)
# Crate a Pipe for interprocess communication
main_conn, detect_conn = Pipe()
# Create a thread in main process to listen on connection
listen_for_interrupt_thread = Thread(
target=listen_for_interrupt, args=(main_conn, sock), daemon=True)
listen_for_interrupt_thread.start()
# Create a separate process to detect the KeyboardInterrupt
detect_interrupt_process = Process(
target=detect_interrupt, args=(detect_conn,))
detect_interrupt_process.start()
connection = None
try:
while True:
print("Running socket accept()")
connection, address = sock.accept()
print("connected from " + address)
received_message = sock.recv(300)
if not received_message:
break
connection.sendall(b"hello")
except KeyboardInterrupt:
print("Handling KeyboardInterrupt")
sock.close()
if connection:
connection.close()
For windows users,
Above solutions which try to catch KeyBoard interrupts don't seem to work. I ended up setting a timeout on my socket.
Something like:
server_socket.settimeout(10)
Here an exception is raised after 10 seconds of inactivity (like not receiving anything for 10 secs)
If the far-end sends data rarely, you should set timeout for the connection as well.
In this case the connection will raise timeout Exception, when the KeyboardInterrupt can be checked.
from socket import socket, AF_INET, SOCK_STREAM
sock = socket(AF_INET, SOCK_STREAM)
sock.bind(("localhost", 7777))
sock.settimeout(1.0)
sock.listen(1)
while True:
try:
connection, address = sock.accept()
connection.settimeout(1.0)
print("connected from " + address)
received_message = sock.recv(300)
if not received_message:
break
connection.sendall(b"hello")
except socket.timeout:
continue
except IOError as msg:
print(msg)
continue
except KeyboardInterrupt:
try:
if connection:
connection.close()
except: pass
break
sock.shutdown
sock.close()