Multithreaded socket programming in python - python

I am working on client/server socket programming using python. I could set it up without any issue, but with threads, I am lost. I don't have a clue how to get that part done. I looked at the python documentation as well, but I could not find what I was expecting.
What I am trying to achieve is - Server is accepting the connection from the client as well as monitoring a directory for any file creation. I am trying to run both of them in parallel, but it didn't work.
#!/usr/bin/python # This is server.py file
import socket # Import socket module
import sys,os
import time
from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler
class MyHandler(PatternMatchingEventHandler):
patterns = ["*.challenger", "*.challenger"]
def process(self, event):
"""
event.event_type
'modified' | 'created' | 'moved' | 'deleted'
event.is_directory
True
event.src_path
/home/abcd/Maildir/new/
"""
# the file will be processed there
print event.src_path, event.event_type # print now only for degug
def on_modified(self, event):
self.process(event)
flag = '1'
print flag
def on_created(self, event):
self.process(event)
def on_any_event(self,event):
if event.event_type == 'created':
send()
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12346 # Reserve a port for your service.
s.bind((host, port)) # Bind to the port
flag = '0'
s.listen(5) # Now wait for client connection.
while True:
c, addr = s.accept() # Establish connection with client.
print 'Got connection from', addr
# c.send('Thank you for connecting')
# c.send(flag)
if __name__ == '__main__':
args = sys.argv[1:]
observer = Observer()
observer.schedule(MyHandler(), path='/home/abcd/Maildir/new')
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
c.send(flag)
c.close() # Close the connection
The code I posted is without threads because with thread it didn't work at all.
I am using watchdog to monitor /home/abcd/Maildir/new to monitor any new e-mail file created, and if it is created I want to send acknowledgement (flag, in this case) to the client that the e-mail has been received. Socket connection and Watchdog worked well individually, but I don't know why they wouldn't work together? :(
How can I put these methods in different threads so that they run parallelly? Thanks for your help.
EDIT: code after Craig's input:
import threading
import socket # Import socket module
import sys,os
import time
from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler
def send_message(conn, flag):
conn.send(flag)
class MyHandler(PatternMatchingEventHandler):
patterns = ["*.challenger", "*.challenger"]
def __init__(self, conn, *args, **kwargs):
super(MyHandler, self).__init__(*args, **kwargs)
self.conn_list = conn
def process(self, event):
"""
event.event_type
'modified' | 'created' | 'moved' | 'deleted'
event.is_directory
True
event.src_path
/home/abcd/Maildir/new/
"""
print "I reached here too"
time.sleep(5)
print event.src_path, event.event_type # print now only for degug
def on_created(self, event):
flag = '1'
threads = [threading.Thread(target=send_message, args=(conn, flag)) for conn in self.conn_list]
for t in threads:
t.start()
print "on_created"
self.process(event)
for t in threads:
t.join()
from collections import deque
conn_list = deque()
if __name__ == '__main__':
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12346 # Reserve a port for your service.
s.bind((host, port)) # Bind to the port
flag = '0'
s.listen(5) # Now wait for client connection.
observer = Observer()
observer.schedule(MyHandler(conn_list), path='/home/abcd/Maildir/new/')
observer.start()
print "Before True"
while True:
try:
c, addr = s.accept() # Establish connection with client.
print 'Got connection from', addr
conn_list.append(c)
time.sleep(1)
print "I started Observer"
except KeyboardInterrupt:
observer.stop()
while conn_list:
conn_list.pop().close()
print "Connections closed"
break
observer.join()
EDIT 2 :
When I send e-mail from client to server, I get the correct result first time but when I connect one more time, the output is weird ("In message" prints twice, flag value also prints twice and I get broken pipe error)
Modified Server.py after Craig's input:
import threading
import socket # Import socket module
import sys,os
import time
from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler
def send_message(conn, flag):
print "In message"
conn.send(flag)
print "flag"+flag
class MyHandler(PatternMatchingEventHandler):
patterns = ["*.challenger", "*.challenger"]
def __init__(self, conn, *args, **kwargs):
super(MyHandler, self).__init__(*args, **kwargs)
self.conn_list = conn
def process(self, event):
time.sleep(5)
print "In process"
print event.src_path, event.event_type # print now only for degug
def on_created(self, event):
flag = '1'
print "before process event"
self.process(event)
print "after process, before thread target"
threads = [threading.Thread(target=send_message, args=(conn, flag)) for$
flag = '0'
for t in threads:
t.start()
# print "Before process(Event)"
# self.process(event)
print "after process event"
for t in threads:
t.join()
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12345 # Reserve a port for your service.
s.bind((host, port)) # Bind to the port
flag = '0'
s.listen(5) # Now wait for client connection.
print "flag before: "+flag
from collections import deque
conn_list = deque()
if __name__ == '__main__':
observer = Observer()
observer.start()
args = sys.argv[1:]
observer.schedule(MyHandler(conn_list), path='/home/abcd/Maildir/new')
while True:
try:
c, addr = s.accept() # Establish connection with client.
print 'Got connection from', addr
flag = '0'
print flag
conn_list.append(c)
except KeyboardInterrupt:
observer.stop()
while conn_list:
conn_list.pop().close()
print "Connections closed"
break
observer.join()
Here's the output:
Got connection from ('72.123.27.223', 39844)
0
before process event
In process
/home/abcd/Maildir/new/1425403821.V801I2ac232cM275759.challenger created
after process, before thread target
In message
In message
flag1In message
after process event
flag1
Exception in thread Thread-7:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "/home/paras/server42.py", line 11, in send_message
conn.send(flag)
error: [Errno 32] Broken pipe
Here's my client.py - All I am trying to do is check e-mail latency from client to server and getting response back from the server.
#!/usr/bin/python # This is client.py file
import sys,smtplib
import socket # Import socket module
import threading,time
import urllib
import random
import datetime
#class myThread(threading.Thread):
# def __init__ (self,name):
# threading.Thread.__init__(self)
# self.name=name
# def run(self):
# connection()
# print "Starting"+self.name
def connection():
s = socket.socket() # Create a socket object
host = socket.gethostbyname('server.edu') # Get local machine name
port = 12345 # Reserve a port for your service.
try:
s.connect((host, port))
# print s.recv(1024)
t1 = datetime.datetime.now()
sendmail()
t2 = datetime.datetime.now()
print str(t1),str(t2)
print "Time taken to send e-mail from client to server: "+str(t2-t1)
print "came back"
flag = s.recv(1024)
print flag
if (flag=='1'):
t3=datetime.datetime.now()
print "Time taken to receive response from server: "+str(t3-t2)
s.close # Close the socket when done
except KeyboardInterrupt:
s.close
def sendmail():
fromaddr = 'xyz#gmail.com'
toaddrs = 'email#server.edu'
url = "http://www.google.com"
seq = str(random.randint(1,9))
msg = 'URL: '+ url + '\n'+'SEQ:'+seq+'\n'
print "In sendmail"
#print msg
# Credentials (if needed)
username = 'xyz#gmail.com'
password = 'somepassword'
#The actual mail send
server = smtplib.SMTP('smtp.gmail.com:587')
#server = smtplib.SMTP('localhost')
server.starttls()
server.login(username,password)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
print "email sent"
return
if __name__ == "__main__":
connection()
Please help me out. Thanks.

This doesn't exactly do what you asked since the server doesn't send the data but I think it achieves what you want to do. You could pass along connection object so that you can send the flag to it from MyHandler.
class MyHandler(PatternMatchingEventHandler):
patterns = ["*.challenger", "*.challenger"]
def __init__(self, conn, *args, **kwargs):
super(MyHandler, self).__init__(*args, **kwargs)
self.conn_list = conn
def process(self, event):
time.sleep(5)
print event.src_path, event.event_type # print now only for degug
def on_created(self, event):
self.process(event)
c = self.conn_list.pop()
c.send('1')
c.close()
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12346 # Reserve a port for your service.
s.bind((host, port)) # Bind to the port
flag = '0'
s.listen(5) # Now wait for client connection.
from collections import deque
conn_list = deque()
if __name__ == '__main__':
observer = Observer()
observer.start()
args = sys.argv[1:]
observer.schedule(MyHandler(conn_list), path='/home/abcd/Maildir/new')
while True:
try:
c, addr = s.accept() # Establish connection with client.
print 'Got connection from', addr
conn_list.append(c)
except KeyboardInterrupt:
observer.stop()
while conn_list:
conn_list.pop().close()
print "Connections closed"
break
observer.join()

Related

Sending and receiving using sockets python

I am trying to create a function to send and receive information over a socket client & server. It appears that my code is somehow blocking. In the code the first command iteration in my for loop is carried out but then the process becomes blocked. Does anyone have any suggestions how to do this using threading or multithreading?
My code is below:
import socket
import json
import sys
import time
import select
import queue
Ni_Rio_IP= "172.22.11.2"
Ni_Base_IP= "172.22.11.1"
class AliceRio:
def __init__(self, ip_rio, ip_pc):
self.ip_rio = ip_rio
AliceRio.udp_port_rio = 60006
self.ip_pc = ip_pc
AliceRio.udp_port_pc = 50005
AliceRio.json= '{"Dest":"","Name":"","Time":"","Val":{"Str":[],"Pos":[[]],"Data":[[]]},"IP":0,"Port":0,"RT error":{"status":false,"code":0,"source":""}}'
AliceRio.dict= json.loads(self.json)
def PrintUDP(self):
print("RIO IP: %s" % self.ip_rio)
print("RIO UDP port: %s" % self.udp_port_rio)
print("PC IP: %s" % self.ip_pc)
print("PC UDP port: %s" % self.udp_port_pc)
def SendRec(self, send_str):
# Set up socket for sending
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # Internet, UDP
sock.sendto(bytes(send_str, 'utf-8'), (self.ip_rio, self.udp_port_rio))
sock.close()
print('got here')
# Set up socket for receiving
sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # Internet, UDP
sock.bind((self.ip_pc, self.udp_port_pc))
rec_str, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
print('got here2')
sock.close()
return rec_str
def Receive(self, rec_str):
sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # Internet, UDP
sock.bind((self.ip_pc, self.udp_port_pc))
rec_str, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
sock.close()
return rec_str
def Send(self, send_str):
# Set up socket for sending
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # Internet, UDP
sock.sendto(bytes(send_str, 'utf-8'), (self.ip_rio, self.udp_port_rio))
sock.close()
#return rec_str
def Aim(self, aim_perc):
if aim_perc < 0 or aim_perc > 100: return "aim_perc out of range"
send_dict=AliceRio.dict
send_dict["Dest"]='Rio'
send_dict["Name"]='Laser Control'
Laser_Mode=1
Simmer_A=0
Pulse_A= 0
Pulse_ms= 20
send_dict["Val"]["Str"]=[str(Laser_Mode), str(aim_perc), str(Simmer_A), str(Pulse_A), str(Pulse_ms)]
send_json=json.dumps(send_dict)
# send it out
self.SendRec(send_json)
rec_json= self.SendRec(send_json)
rec_dict=json.loads(rec_json)
return "Aim laser now at " + rec_dict["Val"]["Str"][1] +'%'
def PWM_Laser_Fan(self, fan_perc):
send_dict=AliceRio.dict
send_dict["Dest"]='Rio'
send_dict["Name"]='PWM Laser'
send_dict["Val"]["Str"][0]=str(fan_perc)
send_json=json.dumps(send_dict)
# send it out
rec_json= self.SendRec(send_json)
rec_dict=json.loads(rec_json)
return rec_dict["Val"]["Str"][0]
def Poll(self):
send_dict=AliceRio.dict
send_dict["Dest"]='Rio'
send_dict["Name"]='Poll'
send_json=json.dumps(send_dict)
# send it out
rec_json= self.SendRec(send_json)
rec_dict=json.loads(rec_json)
if rec_dict["Val"]["Data"][0][0]==0: pid_mode='off'
else: pid_mode='PID'
print('PID mode:', pid_mode)
print('Pos X:', rec_dict["Val"]["Data"][0][1])
print('Pos Y:', rec_dict["Val"]["Data"][0][2])
print('Home:', rec_dict["Val"]["Data"][0][3])
print('Enabled:', rec_dict["Val"]["Data"][0][4])
def PIDControl(self, pid_mode,pid_center):
if pid_mode=="off": mode= 0
elif pid_mode=="PID":mode =1
else: return "pid_mode not valid"
if pid_center[0] not in range(-2048,2048): return "center x-pos not in range"
if pid_center[1] not in range(-2048,2048): return "center y-pos not in range"
send_dict=AliceRio.dict
send_dict["Dest"]='Rio'
send_dict["Name"]='PID Control'
send_dict["Val"]["Str"]=[str(mode), str(pid_center[0]), str(pid_center[1])]
send_json=json.dumps(send_dict)
# send it out
rec_json= self.SendRec(send_json)
rec_dict=json.loads(rec_json)
return "PID mode now at " + rec_dict["Val"]["Str"][0]
Alice1 = AliceRio(Ni_Rio_IP, Ni_Base_IP)
Alice1.PrintUDP()
for i in range(10):
Alice1.Aim((i*10)+10)
time.sleep(0.2)
I would suggest learning to use Pdb and trace through the execution of your program to find where it is getting caught.
Also when learning/developing with sockets I've found that it helps to have separate programs for your client and server in the beginning so you can see how both sides are handling exchanges instead of going the threading route to start since the logging can get confusing, best of luck!
Module threading does help in this scenario.
We can create a thread to receiving incoming messages. And when new message received the thread trigger an event to notify the waiting method SendRec.
import sys
import socket
import json
import threading
import time
class AliceRio:
def __init__(self, .....):
# .........
self.s_in = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.s_in.bind((self.ip_pc, self.udp_port_pc))
self.evt = threading.Event()
self.last_msg = None
def _recv(self):
while True:
msg, _ = self.s_in.recvfrom(1024)
self.last_msg = msg
self.evt.set()
def SendRec(self, send_str):
if not hasattr(self, 'th_recv'):
th = threading.Thread(target=self._recv)
th.setDaemon(True)
th.start()
self.th_recv = th
self.evt.clear()
rio_endpoint = (self.ip_rio, self.udp_port_rio)
s_out = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s_out.sendto(bytes(send_str, 'utf-8'), rio_endpoint)
s_out.close()
if self.evt.wait(timeout=15.0) and self.last_msg:
return self.last_msg
raise Exception('timeout waiting for response.')

P2P Network: Python sockets not receiving data from other nodes

I have checked the documentation online and several Stackoverflow posts, but cannot debug my code. I think I am incorrectly sending bytes, so the other nodes connected to the socket cannot 'hear' the calls.
Is there something wrong with my use of sendall(), or something wrong with how I'm packing my bytestring?
import logging
from random import randint
import socket
import sys
import time
import threading
class Server:
connections = list()
peers = list()
def __init__(self):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('0.0.0.0', 10000))
s.listen(1)
logging.info('Successfully started the server on port 10000.')
while True:
c, a = s.accept()
logging.info('New client node joins pool.')
t = threading.Thread(target=self.handler, args=(c, a))
t.daemon = True
t.start()
self.connections.append(c)
self.peers.append(a[0])
logging.info('New node connected: {}'.format(str(a[0])))
self.send_peers()
def handler(self, c, a):
while True:
data = c.recv(1024)
logging.info('Sending data: {}'.format(data))
for connection in self.connections:
connection.sendall(data)
if not data:
logging.info('Node disconnected: {}:{}'.format(str(a[0]), str(a[1])))
self.connections.remove(c)
self.peers.remove(a[0])
c.close()
self.send_peers()
break
def send_peers(self):
"""Sends the list of peers in the swarm to all connected peers."""
p = ''
for peer in self.peers:
p = p + peer + ','
for connection in self.connections:
connection.sendall(b'\x11' + p.encode())
class Client:
def __init__(self, address):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.connect((address, 10000))
logging.info('Successfully made a client connection at: {}. Listening..'.format(address))
t = threading.Thread(target=self.send_message, args=(s,))
t.daemon = True
t.start()
while True:
data = s.recv(1024)
print(data)
if not data:
break
if data[0:1] == b'\x11':
# Message prefixed with \x11, so we know it is a new node message
self.update_peers(data[1:])
else:
# Since the message received isn't prefixed with \x11, we know it is a message
logging.info('Received message: {}'.format(data.decode()))
#staticmethod
def send_message(s):
"""Sends a message to all connected nodes."""
while True:
message = str(input('Enter message: ')).encode()
s.sendall(message)
logging.info('Sending message: {}'.format(message.decode()))
#staticmethod
def update_peers(peer_data):
"""Refreshes the local copy of all connected nodes."""
logging.info('Node dropped/connected. Updating connected peers list.')
Tracker.peers = peer_data.decode.split(',')[:-1]
class Tracker:
"""Tracks the Peers connected within the swarm.
This is a separate class due to data accessibility. We want to be able to access the peers list
from outside the Client and Server classes.
"""
peers = ['127.0.0.1']
if __name__ == '__main__':
logging.basicConfig(format='%(asctime)s %(levelname)-8s %(message)s',
level=logging.INFO,
datefmt='%Y-%m-%d %H:%M:%S')
logging.info('Connecting..')
while True:
try:
time.sleep(randint(1, 5))
for peer in Tracker.peers:
try:
server = Server()
except KeyboardInterrupt:
sys.exit(0)
except:
logging.warning('Server is already started. Becoming a client node.')
try:
client = Client(peer)
except KeyboardInterrupt:
sys.exit(0)
except:
logging.warning('Could not become a client node.')
pass
except KeyboardInterrupt:
sys.exit(0)

How to get the modbus_tk master's IP?

I write a slave.py(server) base on modbus_tk(https://github.com/ljean/modbus-tk).
Then,I use the client tools to connect the slave,It's OK.
And now,I want to get which master(client) access to me,I want to get source IP and port.
I find the key point 'client, address = self._sock.accept()' in function _do_run(self) in Class TcpServer(server) ,modbus_tcp.py.
I tried some methods, but it didn't work.
slave.py
import modbus_tk
import modbus_tk.modbus_tcp as modbus_tcp
import modbus_tk.defines as mdef
import threading
import sys
from lxml import etree
logger = modbus_tk.utils.create_logger(name='console', record_format='%(message)s')
server = modbus_tcp.TcpServer(port=502,address='0.0.0.0')
class Modbus_server(object):
def main(self):
try:
logger.info("running...")
logger.info("enter 'quit' for closing the server")
server.start()
self.config_slaves()
while True:
cmd = sys.stdin.readline()
if cmd.find('quit')==0:
#when input"quit",the program exit!
sys.stdout.write('bye-bye\r\n')
sys.exit(0)
finally:
server.stop()
#get slave configuration
def config_slaves(self):
dom = etree.parse('modbus.xml')
slaves = dom.xpath('//modbus/slaves/*')
try:
for s in slaves:
slave_id = int(s.attrib['id'])
slave = server.add_slave(slave_id)
logger.debug('Added slave with id %s.', slave_id)
for b in s.xpath('./blocks/*'):
name = b.attrib['name']
request_type = eval('mdef.' + b.xpath('./type/text()')[0])
start_addr = int(b.xpath('./starting_address/text()')[0])
size = int(b.xpath('./size/text()')[0])
slave.add_block(name, request_type, start_addr, size)
logger.debug(
'Added block %s to slave %s. '
'(type=%s, start=%s, size=%s)',
name, slave_id, request_type, start_addr, size)
logger.info('modbus initialized')
except (Exception) as e:
logger.info(e)
modbus=Modbus_server()
modbus.main()`
modbus_tcp.py
''''''
......
def _do_run(self):
"""called in a almost-for-ever loop by the server"""
#check the status of every socket
inputready = select.select(self._sockets, [], [], 1.0)[0]
#handle data on each a socket
for sock in inputready:
try:
if sock == self._sock:
# handle the server socket
client, address = self._sock.accept()
client.setblocking(0)
LOGGER.info("%s is connected with socket %d...", str(address), client.fileno())
self._sockets.append(client)
call_hooks("modbus_tcp.TcpServer.on_connect", (self, client, address))
''''''
''''''

Thread a server to accept more than one client doesn't work properly

Well, I'm trying to make a simple Network TCP chatting program to dive deeper in python, threading and networking. The program worked but with just one user, I looked this up, I found that I need threading to make the server accept more than one user. I threaded the server but now when you connect the second user it disconnect the first one. Source code may not be that good..
#!/usr/bin/python
import socket, sys, threading
from time import sleep
# Global Stuff
localhost = socket.gethostbyname(socket.gethostname())
#localhost = '192.168.x.x'
serverPort = 5003
buffer = 1024 #Bytes
backlog = 5
userThread= []
count = 0
class server(object):
''' Constructor to Establish Bind server once an object made'''
def __init__(self, localhost, serverPort): # Connect Tcp
global backlog, count
self.servSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
self.servSock.bind((localhost, serverPort))# bind((host,Port))
self.servSock.listen(backlog)
print count
except Exception, e:
print "[Bind ]", e
sys.exit()
def accept(self):
global userThread, conn, addr, count
"""
- PROBLEM IS IN HERE SOMEWHERE SERVER DOESN'T ADD THE OTHER CLIENT EXCEPT ONCE.
- THREAD DOEN'T KEEP THE CLIENT.
- THE SECOND CLIENT FREEZES WHILE SENDING THE VERY FIRST MESSAGE TILL THE FIRST
CLIENT SEND A MESSAGE THEN IT CAN SEND MESSAGES AND THE FIRST CLIENT CAN'T SEND SHIT.
"""
count+=1
while True:
print count
self.conn, self.addr = self.servSock.accept()
conn = self.conn
print("This is a connection: ", conn)
#acceptThread = threading.start_new_thread(target=serverObj.accept, args=(conn))
#addr = self.addr
print "[Listening..]"
if(self.addr not in userThread):
userThread.append(self.addr)
print "Client's added Successfully"
else:
pass
def redirect(self):
global buffer, userThread, conn, count
count+=1
while True:
try:
print "Redirecting " + str(count)
self.data = conn.recv(buffer)
if self.data:
for user in userThread:
#conn.send(b'Recieved by server!\n')
conn.sendto("Sent!\n"+self.data+"\n", user)
print "Server: Data sent[" +self.data+"] to ["+str(user)+"]"
else:
self.data = conn.recv(buffer)
print "No dataa found"
except Exception, e:
print "[Redirect ] ",e
sleep(7)
print "OUT"# testing if it's getting out this infinite loop.
def exit(self):
self.server.close()
def main():
global localhost, serverPort, conn
try:
serverObj = server(localhost, serverPort)
print("[+] Server is UP!")
except Exception, e:
print "[Main ] ",e
exit()
acceptThread = threading.Thread(name = "Accepting Connections", target=serverObj.accept)
redirThread = threading.Thread(name = "Redirecting Data", target=serverObj.redirect)
acceptThread.start()
redirThread.start()
print userThread
main()
######################################### Client ##########################################
#!/usr/bin/python
# This is client file
"""
http://eli.thegreenplace.net/2011/05/18/code-sample-socket-client-thread-in-python
https://docs.python.org/2/library/threading.html
"""
import socket
import threading
from time import sleep
# Client Info
#clientSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#localhost = '192.168.x.x'
# Global Stuff
serverIP = socket.gethostbyname(socket.gethostname())
#serverIP = '192.168.x.x'
serverPort, MsgSendError, MsgSendSucc, clientPort, data, buffer =\
5003, False, True, 12345, '',1024 #Bytes
class client(object):
global MsgSendError, MsgSendSucc, buffer, data
''' Constructor to Establish Connection once client is up'''
def __init__(self, serverIP, serverPort): # Connect Tcp
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
self.sock.connect((serverIP, serverPort))
except Exception, e:
return "[Connecting to Server]", e
def send(self, data):
try:
self.sock.send(data) # covnert it from string into byte streams to be in proper format.
#print str(data)
return MsgSendSucc
except:
return MsgSendError
def receive2(self):
try:
data = self.sock.recv(buffer)
#print "Function: Receive2."# testing
#print(str(data))# testing
#print "Received!"# testing
return str(data)
except Exception, e:
return "[In receive2]", e
def main():
global serverIP, serverPort, data#, sock
clientObj = client(serverIP, serverPort)
alias = raw_input("Your Name USER! ")
sentData = ''
while sentData is not 'Quit':
sentData = raw_input("Data>> ")
data = alias + ": "+sentData
if clientObj.send(data) == MsgSendSucc:
#print "Sent!"
#print "Fetching..\n"# testing
print(clientObj.receive2())
# testing
main()

Manipulating socketstream in Python

I'm trying to create a small, multithreaded proxyscript that allows me to proxy LDAP requests and manipulate the results (like adding extra fields, renaming them etc).
In the example below, I try to replace the field 'TEST' by 'DONE'. Is there any solution to allow this socketstream to be manipulated? Should I decode it somewhat first?
import select
import socket
import sys
import threading
import signal
import re
import random
import time
import binascii
from ldaptor.protocols import pureldap, pureber
from time import gmtime, strftime
ASTLDAP_PROXY_PORT = 1389
ASTLDAP_HOST = 'localhost'
ASTLDAP_PORT = 389
BUFFERSIZE = 1024
DELAY = 0.0001
class Forward:
def __init__(self):
self.forward = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def start(self, host, port):
try:
self.forward.connect((host, port))
return self.forward
except Exception, e:
print e
return False
class AstLdapProxyServer(threading.Thread):
input_list = []
channel = {}
def __init__(self, host, port, socket):
threading.Thread.__init__(self)
self.host = host
self.port = port
# Socket ontvangen die we meekregen bij nieuwe thread.
self.socket = socket
print "[+] New thread started for "+host+":"+str(port)
self.socket.bind((host, port))
self.socket.listen(200)
def register_signals(self):
signal.signal(signal.SIGHUP, self.signal_handler)
signal.signal(signal.SIGINT, self.signal_handler)
signal.signal(signal.SIGQUIT, self.signal_handler)
def main_loop(self):
self.input_list.append(self.socket)
while 1:
#time.sleep(DELAY)
ss = select.select
inputready, outputready, exceptready = ss(self.input_list, [], [])
for self.s in inputready:
if self.s == self.socket:
self.on_accept()
break
self.data = self.s.recv(BUFFERSIZE)
if len(self.data) == 0:
self.on_close()
else:
self.on_recv()
def on_accept(self):
forward = Forward().start(ASTLDAP_HOST, ASTLDAP_PORT)
clientsock, clientaddr = self.socket.accept()
if forward:
print clientaddr, "has connected"
self.input_list.append(clientsock)
self.input_list.append(forward)
self.channel[clientsock] = forward
self.channel[forward] = clientsock
else:
print "Can't establish connection with remote server.",
print "Closing connection with client side", clientaddr
clientsock.close()
def on_close(self):
print self.s.getpeername(), "has disconnected"
#remove objects from input_list
self.input_list.remove(self.s)
self.input_list.remove(self.channel[self.s])
out = self.channel[self.s]
# close the connection with client
self.channel[out].close() # equivalent to do self.s.close()
# close the connection with remote server
self.channel[self.s].close()
# delete both objects from channel dict
del self.channel[out]
del self.channel[self.s]
def on_recv(self):
data = self.data
# Manipulate result
output = re.sub(r'uzgEmail1', r'TEST', data)
# Send result to client (DOESN'T WORK)
self.channel[self.s].send(output)
# Send result to client (WORKS when I disable send above)
self.channel[self.s].send(data)
if __name__ == '__main__':
tcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpsock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
server = AstLdapProxyServer(ASTLDAP_HOST, ASTLDAP_PROXY_PORT, tcpsock)
server.start()
try:
server.main_loop()
except KeyboardInterrupt:
sys.exit(1)

Categories