I'm working on a project wich consist on testing a board connection with a JTAG connector and OpenOCD server.
Here is the connection class I've coded, it's simply using pexpect :
"""
Communication with embedded board
"""
import sys
import time
import threading
import Queue
import pexpect
import serial
import fdpexpect
from pexpect import EOF, TIMEOUT
class ModTelnet():
def __init__(self):
self.is_running = False
self.HOST = 'localhost'
self.port = '4444'
def receive(self):
#receive data (= msg) from telnet stdout
data = [ EOF, TIMEOUT, '>' ]
index = self._tn.expect(data, 2)
if index == 0:
return 'eof', None
elif index == 1:
return 'timeout', None
elif index == 2:
print 'success', self._tn.before.split('\r\n')[1:]
return 'success',self._tn.before
def send(self, command):
print 'sending command: ', command
self._tn.sendline(command)
def stop(self):
print 'Connection stopped !'
self._ocd.sendcontrol('c')
def connect(self):
#connect to MODIMX27 with JTAG and OpenOCD
self.is_running = True
password = 'xxxx'
myfile = 'openocd.cfg'
self._ocd = pexpect.spawn('sudo openocd -f %s' % (myfile))
i = self._ocd.expect(['password', EOF, TIMEOUT])
if i == 0:
self._ocd.sendline(password)
time.sleep(1.0)
self._connect_to_tn()
elif i == 1:
print ' *** OCD Connection failed *** '
raise Disconnected()
elif i == 2:
print ' *** OCD Connection timeout *** '
raise Timeout()
def _connect_to_tn(self):
#connect to telnet session # localhost port 4444
self._tn = pexpect.spawn('telnet %s %s' % (self.HOST, self.port))
condition = self._tn.expect(['>', EOF, TIMEOUT])
if condition == 0:
print 'Telnet opened with success'
elif condition == 1:
print self._tn.before
raise Disconnected()
elif condition == 2:
print self._tn.before
raise Timeout()
if __name__ =='__main__':
try:
tn = ModTelnet()
tn.connect()
except :
print 'Cannot connect to board!'
exit(0)
The problem is when I'm trying to use send, receive and stop command in ohter modules doing this :
>>> from OCDConnect import *
>>> import time
>>> tn = ModTelnet()
>>> tn.connect()
Telnet opened with success
>>> time.sleep(2.0)
>>> self.send('soft_reset_halt')
MMU: disabled, D-Cache: disabled, I-Cache: disabled
>>> self.stop()
It give me an error like : "ModTelnet has no send attribute"
How can I fix this??
Thanks for you help !
try
'send' in dir(tn)
if it's False, you haven't implemented the send method.
The problem was the syntax of my class definition :
class ModTelnet:
And not :
class ModTelnet():
wich is a useless because I don't inherit from an other class ... :D
Thanks anyway !
Related
I did debug the code below, line-by-line using some print statements.
class Timeout(Exception):
pass
def getSource(comm):
source = comm.split('#')
params = source[1].split(':')
debug = '--debug' in sys.argv
if source[0] == 'serial':
try:
return Serial(params[0], int(params[1]), flush=True, debug=debug)
except:
print ("ERROR: Unable to initialize a serial connection to", comm)
raise Exception
Everything looks OK until the line:
return Serial(params[0], int(params[1]), flush=True, debug=debug)
this line is supposed to be compiled since all the objects in the Serial like params[0], etc are obtained. But it returns an error jumping to the except and printing the statement "ERROR: Unable to initialize a serial connection to ..."
I am using Python 3.6.8 on a Docker container.
Any kind of help would be appreciated. I'm ready for any further info, if needed.
Here, I post the Serial. I hope this helps you guys to better understand my issue.
class Serial:
def __init__(self, port, baudrate, flush=False, debug=False, readTimeout=None, ackTimeout=0.02):
self.debug = debug
self.readTimeout = readTimeout
self.ackTimeout = ackTimeout
self._ts = None
if port.startswith('COM') or port.startswith('com'):
port = int(port[3:]) - 1
elif port.isdigit():
port = int(port) - 1
self._s = serial.Serial(port, int(baudrate), rtscts=0, timeout=0.5)
self._s.flushInput()
if flush:
print >>sys.stdout, "Flushing the serial port",
endtime = time.time() + 1
while time.time() < endtime:
self._s.read()
sys.stdout.write(".")
if not self.debug:
sys.stdout.write("\n")
self._s.close()
self._s = serial.Serial(port, baudrate, rtscts=0, timeout=readTimeout)
def getByte(self):
c = self._s.read()
if c == '':
raise Timeout
#print 'Serial:getByte: 0x%02x' % ord(c)
return ord(c)
def putBytes(self, data):
#print "DEBUG: putBytes:", data
for b in data:
self._s.write(struct.pack('B', b))
time.sleep(0.000001)
def getTimeout(self):
return self._s.timeout
def setTimeout(self, timeout):
self._s.timeout = timeout
I implemented a simple network 'game' in Python - server draws a random number, and then the client tries to guess it. My application works great, when the client guesses the number, it disconnects from server (it is handled on client's side).
However, after the proper guess, the number is still the same. I would like to modify the application, such that when the client guesses the number, the server should then rand a new number, so other clients should guess the new one. How can I do this?
Some template, just to draw an attention to the problem:
#!/usr/bin/env python
from random import randint
import socket, select
from time import gmtime, strftime
import threading
import sys
class Handler(threading.Thread):
def __init__(self, connection, randomnumber):
threading.Thread.__init__(self)
self.connection = connection
self.randomnumber = randomnumber
def run(self):
while True:
try:
data = self.connection.recv(1024)
if data:
print data
try:
num = int(data)
if Server.guess(num) :
msg = "You won! This is the right number!"
self.connection.send(msg)
break
else :
msg = "Try again!"
self.connection.send(msg)
except ValueError, e:
msg = "%s" % e
self.connection.send(msg)
else:
msg = "error"
self.connection.send(msg)
except socket.error:
self.connection.close()
break
self.connection.close()
class Server:
def __init__(self, ip, port):
self.ip = ip
self.port = port
self.address = (self.ip, self.port)
self.server_socket = None
self.randnum = randint(1, 100)
#classmethod
def guess(cls, no):
if cls.randnum == no:
cls.randnum = randint(1, 1000)
result = True
else:
result = False
return reslut
def run(self):
try:
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.bind((self.ip, self.port))
self.server_socket.listen(10)
print 'Num is %s' % self.randnum
while True:
connection, (ip, port) = self.server_socket.accept()
c = Handler(connection, self.randnum)
c.start()
except socket.error, e:
if self.server_socket:
self.server_socket.close()
sys.exit(1)
if __name__ == '__main__':
s = Server('127.0.0.1', 1234)
s.run()
Generate the random number that is shared between both server and all the client, there should be only instance of this, hence this should be class attribute.
Add a class function guess which return False upon incorrect guess and upon correct guess changes the randnum and returns True
class Server:
randnum = randint(1, 1000) # class attribute created
#classmethod
def guess(cls, no): # To be used "guess" if `no` attribute if the same as `cls.randnum`
if cls.randnum == no:
cls.randnum = randint(1, 1000)
result = True
else:
result = False
return result
def __init__(self, ip, port):
# ...
The client should call this Server.guess function each time.
Actually your issue comes from the fact that you create randnum as an instance method (see your self.randnum) as #shanmuga explained, if you simply declare it as being a class attribute, and remove the instance method it solves your issue (i.e. declaring it in the class directly).
As a side issue (not being an expert on socket), when you send message to the client, you might want to encode them as a byte object (in the run method of Handler, I changed self.connection.send(msg) to self.connection.send(msg.encode())). Also note that I used Python 3.6 (which mainly change the style of print statements)
See the code below:
#!/usr/bin/env python
from random import randint
import socket, select
from time import gmtime, strftime
import threading
import sys
class Handler(threading.Thread):
def __init__(self, connection, randomnumber):
threading.Thread.__init__(self)
self.connection = connection
self.randomnumber = randomnumber
def run(self):
while True:
try:
data = self.connection.recv(1024)
if data:
print(data)
try:
num = int(data)
if Server.guess(num) :
msg = "You won! This is the right number!"
self.connection.send(msg.encode())
break
else :
msg = "Try again!"
self.connection.send(msg.encode())
except ValueError as e:
msg = "%s" % e
self.connection.send(msg.encode())
else:
msg = "error"
self.connection.send(msg.encode())
except socket.error:
self.connection.close()
break
self.connection.close()
class Server:
randnum = randint(1,100)
def __init__(self, ip, port):
self.ip = ip
self.port = port
self.address = (self.ip, self.port)
self.server_socket = None
#classmethod
def guess(cls, no):
if cls.randnum == no:
cls.randnum = randint(1, 1000)
print("New number is ", cls.randnum )
result = True
else:
result = False
return result
def run(self):
try:
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.bind((self.ip, self.port))
self.server_socket.listen(10)
print('Num is %s' % self.randnum)
while True:
connection, (ip, port) = self.server_socket.accept()
c = Handler(connection, self.randnum)
c.start()
except socket.error as e:
if self.server_socket:
self.server_socket.close()
sys.exit(1)
if __name__ == '__main__':
s = Server('127.0.0.1', 1234)
s.run()
I have client program written in python that talks to some server.
[Client]
import asyncore
import logging
import socket
import sys, threading, traceback
from cStringIO import StringIO
class Client(threading.Thread, asyncore.dispatcher):
def __init__(self, host, port):
self.logger = logging.getLogger()
threading.Thread.__init__(self)
self._thread_sockets = dict()
asyncore.dispatcher.__init__(self, map=self._thread_sockets)
# data members for the module
self.host = host
self.port = port
self.write_buffer = ""
self.is_connected = False
self.read_buffer = StringIO()
# Ok now to run the thread !!
self.start()
def run(self) :
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
address = (self.host, self.port)
self.logger.debug('connecting to %s', address)
# wait until server is up
while not self.is_connected :
try :
self.connect(address)
except Exception as ex :
pass #do nothing, proceed forward !!
asyncore.loop(map=self._thread_sockets)
def handle_connect(self):
self.is_connected = True
self.logger.debug('handle_connect()')
def handle_close(self):
self.logger.debug('handle_close()')
self.close()
def handle_error(self):
traceback.print_exc(sys.stderr)
self.close()
def writable(self):
self.logger.debug('writable() : len is %d bytes', len(self.write_buffer))
is_writable = (len(self.write_buffer) > 0)
if is_writable:
self.logger.debug('writable() -> %s', is_writable)
return is_writable
def readable(self):
self.logger.debug('readable() -> True')
return True
def handle_write(self):
sent = self.send(self.write_buffer)
self.logger.debug('data len written to socket -> %s', sent)
self.logger.debug('handle_write() -> "%s"', self.write_buffer[:sent])
#self.write_buffer = self.write_buffer[sent:]
def handle_read(self):
data = self.recv(8192)
self.logger.debug('handle_read() -> %d bytes', len(data))
self.read_buffer.write(data)
self.logger.debug('data received from socket -> %s', self.read_buffer.getvalue())
self.read_buffer.truncate(0)
def send(self, data) :
self.write_buffer = data
if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG,
format='%(name)s: %(message)s',
)
try :
client = Client("127.0.0.1", 8182)
client.send('sending data from client')
except Exception as ex :
logging.exception(ex)
sys.exit(1)
I am able to receive data from server correctly but send call to the server always fails. As from the log the send always return 'None'.
Am i missing anything ?
You override the send method of asyncore.dispatcher with code that does not send any data and returns no value:
def send(self, data) :
self.write_buffer = data
At the least, you need to change your code to look similar to this:
def send_data(self, data):
self.write_buffer = data
and this:
client.send_data('sending data from client')
The asyncore.dispatcher class already has a send method which is a wrapper around the socket.send method. From asyncore.py:
def send(self, data):
try:
result = self.socket.send(data)
return result
except socket.error, why:
if why.args[0] == EWOULDBLOCK:
return 0
elif why.args[0] in _DISCONNECTED:
self.handle_close()
return 0
else:
raise
Because you override this method, your send method gets called in your handle_write method, and no data is sent to the server.
I want 2 processes to communicate on a given port without either one having a defined client or server role. Either of the processes may be running alone. Either may stop and restart at any time, in any order. When they are both running they need to communicate (when only one is running, communication is just discarded).
I want non-blocking sockets and Windows/Linux support.
Here's a rather crude class that actually works to some extent, which might get you started.
The main trick here is not to bother with listen at all: these are pure peer to peer connections, fully specified by the <local-addr, remote-addr> pair.
Note that the sockets are left in non-blocking mode. I caught the recv exception but there can be a send one as well (plus, you get broken-pipe errors when sending to a dead peer, etc). You'll also need to handle EOF-from-terminated-peer (when recv returns '' instead of failing with EAGAIN).
import errno
import os
import select
import socket
class Peer(object):
def __init__(self, local_addr, peer_addr):
self._local_addr = local_addr
self._peer_addr = peer_addr
self._renew()
self.reopen()
def _renew(self):
self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._sock.bind(self._local_addr)
self._sock.setblocking(False)
self._sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self._state = 'bound'
def is_open(self):
return self._state == 'open'
def is_opening(self):
return self._state == 'opening'
def reopen(self):
if self._state == 'open':
raise ValueError('already open')
if self._state == 'opening':
raise ValueError('open in progress')
print 'try connect to:', self._peer_addr
error = self._sock.connect_ex(self._peer_addr)
print 'result:', error
if error == 0:
self._state = 'open'
print 'connected immediately'
elif error in (errno.EINPROGRESS, errno.EINTR):
self._state = 'opening'
print 'connection in progress'
else:
raise socket.error(error, os.strerror(error))
def _check_open(self):
if self._state != 'opening':
raise ValueError('improper call to _check_open')
print 'check connect to:', self._peer_addr
_, wfds, _ = select.select([], [self._sock], [])
if len(wfds) == 0:
# connection still in progress
return
# we have a result: fail or succeed, either way a result
try:
peer = self._sock.getpeername()
except socket.error as err:
print 'caught err:', err
if err.errno == errno.ENOTCONN:
print 'connection failed, no peer available'
self.close()
return
raise
print 'got a peer:', peer
self._state = 'open'
print 'connection finished'
def close(self):
if self._state in ('open', 'opening'):
self._sock.close()
self._renew()
# self.reopen() - or leave to caller
def send_if_connected(self, data):
# to do: add check for send to dead peer, and if so, _renew etc
if self._state == 'bound':
self.reopen()
if self._state == 'opening':
self._check_open()
if self._state == 'open':
self._sock.send(data)
def recv_if_connected(self):
# to do: add check for send to dead peer, and if so, _renew etc
if self._state == 'bound':
self.reopen()
if self._state == 'opening':
self._check_open()
if self._state == 'open':
try:
return self._sock.recv(1024)
except socket.error as err:
# still connected but no data avail
if err.errno == errno.EAGAIN:
return ''
raise
else:
return None
if __name__ == '__main__':
import argparse
import time
parser = argparse.ArgumentParser(description='test Peer()')
parser.add_argument('-l', '--localhost', default='')
parser.add_argument('-p', '--port', type=int, default=9001)
parser.add_argument('-R', '--remote-host', default='')
parser.add_argument('-r', '--remote-port', type=int, default=9002)
args = parser.parse_args()
x = Peer((args.localhost, args.port), (args.remote_host, args.remote_port))
for i in range(1, 10):
print 'attempt to send %d' % i
x.send_if_connected('send %d' % i)
got = x.recv_if_connected()
if got is not None:
print 'got: "%s"' % got
time.sleep(1)
Run with: $ python peerish.py -p 9001 -r 9002 & python peerish.py -p 9002 -r 9001 & for instance.
I must be missing something in the code. I've rewritten an 'echo server' example to do a bit more when it receives something.
This is how it currently looks:
#!/usr/bin/env python
import select
import socket
import sys
import threading
import time
import Queue
globuser = {}
queue = Queue.Queue()
class Server:
def __init__(self):
self.host = ''
self.port = 2000
self.backlog = 5
self.size = 1024
self.server = None
self.threads = []
def open_socket(self):
try:
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind((self.host,self.port))
self.server.listen(5)
except socket.error, (value,message):
if self.server:
self.server.close()
print "Could not open socket: " + message
sys.exit(1)
def run(self):
self.open_socket()
input = [self.server,sys.stdin]
running = 1
while running:
inputready,outputready,exceptready = select.select(input,[],[])
for s in inputready:
if s == self.server:
# handle the server socket
c = Client(self.server.accept(), queue)
c.start()
self.threads.append(c)
elif s == sys.stdin:
# handle standard input
junk = sys.stdin.readline()
running = 0
# close all threads
self.server.close()
for c in self.threads:
c.join()
class Client(threading.Thread):
initialized=0
def __init__(self,(client,address), queue):
threading.Thread.__init__(self)
self.client = client
self.address = address
self.size = 1024
self.queue = queue
self.threads = []
global globuser
print 'Client thread created!'
def run(self):
running = 1
while running:
print 'While running client'
data = self.client.recv(self.size)
print 'Dit we receive data?'
if data:
print 'Data received!'
print 'Fetching data from socket: ',
if data[0] == 'I':
print 'Initializing user: ' + data
user = {'uid': data[1:6] ,'x': data[6:9], 'y': data[9:12]}
globuser[user['uid']] = user
print globuser
initialized=1
m=updateClient(user['uid'], queue)
m.start()
self.threads.append(m)
self.client.send('Beginning - Initialized'+';')
elif data[0] == 'A':
print 'Client has received previous data: ' + data
#On deactivation, nothing works.
self.client.send(data+';')
#print 'Client Data sent: ' + data
else:
print 'Closing'
self.client.close()
running = 0
if self.queue.empty():
print 'Queue is empty'
else:
print 'Queue has information: ',
data2 = self.queue.get(1, 1)
isdata2 = 1
if data2 == 'Exit':
running = 0
print 'Client is being closed'
self.client.close()
if isdata2 == 1:
print 'Sending data to client: ' + data2,
self.client.send(data2)
self.queue.task_done()
isdata2 = 0
time.sleep(1)
class updateClient(threading.Thread):
def __init__(self,uid, queue):
threading.Thread.__init__(self)
self.uid = uid
self.queue = queue
global globuser
print 'updateClient thread started!'
def run(self):
running = 20
test=0
while running > 0:
test = test + 1
self.queue.put('Test Queue Data #' + str(test))
running = running - 1
time.sleep(1)
print 'Updateclient has stopped'
if __name__ == "__main__":
s = Server()
s.run()
This runs fine, although it's kind of silly to keep sending the same data back again along with other data.
In the middle of the code you'll see
#On deactivation, nothing works.
self.client.send(data+';')
#print 'Client Data sent: ' + data
When I DO deactive the self.client.send(data+';') or change it into self.client.send('something else;') it does not work! And the client receives nothing.
Is there something special about the "data" variable? Do I need to format the string in some way?
Here's a cleaned-up, functional version of your code! I tested it myself, though I didn't write unit tests.
There were some syntax errors and other miscellaneous problems with the
original code, so I took some liberties. I'm assuming that the protocol is
framed by using ; as a delimiter, since a ; is sent at the end of every
message to the client, though no framing was being done in the original code.
from twisted.internet import reactor, protocol, task
from twisted.protocols import basic
from twisted.python import log
import sys
class ServerProtocol(basic.LineOnlyReceiver):
delimiter = ';'
def lineReceived(self, line):
if line.startswith('I'):
user = dict(uid=line[1:6], x=line[6:9], y=line[9:12])
self.factory.users[user['uid']] = user
log.msg(repr(self.factory.users))
self.startUpdateClient()
self.sendLine('Beginning - Initialized')
elif line.startswith('A'):
self.sendLine(line)
else:
self.transport.loseConnection()
def _updateClient(self):
if self._running == 0:
self._looper.stop()
return
self._running -= 1
self._test += 1
self.sendLine('Test Queue Data #%d' % (self._test,))
def startUpdateClient(self):
self._running, self._test = 20, 0
self._looper = task.LoopingCall(self._updateClient)
self._looper.start(1, now=False)
class Server(protocol.ServerFactory):
protocol = ServerProtocol
def __init__(self):
self.users = {}
if __name__ == '__main__':
log.startLogging(sys.stderr)
reactor.listenTCP(2000, Server())
reactor.run()