HOW TO DO Socket Multiple Clients - python

this is a part from a code that making GUI for process list. I'm trying to do a Socket Multiple Clients but it is'nt working. Can some one help me with this?
import socket, pickle
import threading
import select
BUF_SIZE = 8192
class Network(threading.Thread):
def __init__(self, frame):
threading.Thread.__init__(self)
self.frame = frame
self.server_sock = socket.socket()
def run(self, client_sock=None):
self.server_sock.bind(('', 1729))
self.server_sock.listen(5)
self.open_client_sockets = []
while True:
self.rlist, self.wlist, self.xlist = select.select([self.server_sock] + self.open_client_sockets, [], [])
if self.currect_sock is self.server_sock:
client_sock, client_address = self.server_sock.accept()
self.open_client_sockets.append(self.new_sock)
data = client_sock.recv(BUF_SIZE)
processes_list = pickle.loads(data)
for process_details in processes_list:
self.frame.add_line(process_details)
else:
data = self.client_sock.recv(BUF_SIZE)
processes_list = pickle.loads(data)
for process_details in processes_list:
self.frame.add_line(process_details)
client_sock.close()
self.server_sock.close()
self.server_sock.close()

Related

Socket Freezes recv

everyone.
I send data to the server, it eats them, and then I start waiting for a response from the server by the client, and at this moment both the server and the client hang, but if you send data to the server without waiting for a response from it, it will calmly perform the function without freezes.
Who knows what the problem is?
client
import os
import socket
from time import sleep
import ast
class socker:
def __init__(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect(('localhost', 4545))
def send_request(self, request):
# self.sock.settimeout(5)
self.sock.send(request)
def recieve_request(self):
byte = b""
while True:
data = self.sock.recv(1024)
byte += data
if not data:
break
return byte
def close_connection(self):
self.sock.close()
def test():
s = socker()
s.send_request(str({"request": "get_files_list"}).encode())
s.recieve_request()
test()
server
import socket
import ast
import os
def start_server():
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('localhost', 4545))
print("Сервер включён!")
while True:
try:
server.listen(10)
conn, addr = server.accept()
print('Подключён:', addr)
byte = b""
while True:
data = conn.recv(1024)
byte += data
if not data:
break
data = ast.literal_eval(byte.decode())
request = data["request"]
print("Запрос: ", request)
if request == "get_info_about_file":
pass
elif request == "get_files_list":
files = os.walk(saved_dir)
dirpaths = []
file_names = []
for dirpath, dirnames, filenames in files:
dirpaths.append(dirpath)
print(dirpath)
for file in filenames:
file_names.append(os.path.join(dirpath, file))
conn.send(str({"dirs": dirpaths, "files": file_names}).encode())
conn.shutdown(socket.SHUT_RDWR)
except KeyboardInterrupt:
server.close()
except Exception as err:
print(err)
if __name__ == "__main__":
start_server()

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.')

Python Sockets Port forwarding

So I port forwarded my ip so that my friends can test if my stuff works
And I have a simple server that is hosted on the internal ip
import socket
import threading
class Server:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connections = []
def __init__(self, ip="0.0.0.0", port=5555):
self.sock.bind((ip, port))
self.sock.listen(1)
def handler(self, c, a):
while True:
data = c.recv(4096)
for connection in self.connections:
connection.send(data)
if not data:
print(str(a[0]) + ":" + str(a[1]), "disconnected")
self.connections.remove(c)
c.close()
break
def run(self):
while True:
c, a = self.sock.accept()
rThread = threading.Thread(target=self.handler, args=(c, a))
rThread.daemon = True
rThread.start()
self.connections.append(c)
print(str(a[0]) + ":" + str(a[1]), "connected")
host = Server("192.168.x.xxx", 6667)
print("Server status: Running")
host.run()
And a simple client module that I attempted to pass the public ip to
import socket
import pickle
import threading
import pyaudio
import numpy as np
class Client():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def __init__(self, address):
threading.Thread.__init__(self)
self.sock.connect((address, 6667))
def run(self, id):
RATE = 16000
CHUNK = 256
self.id = id
p = pyaudio.PyAudio()
player = p.open(format=pyaudio.paInt16, channels=1, rate=RATE, output=True, frames_per_buffer=CHUNK)
while True:
data = self.sock.recv(4096)
data = pickle.loads(data)
if data[0] != self.id:
if not data:
break
player.write(np.fromstring(data[1],dtype=np.int16),CHUNK)
def sendMsg(self, data, id):
data1 = [id, data]
self.sock.send(pickle.dumps(data1))
The client does not connect to the server when I try to give it the public address
print("Connecting to server")
cli = Client("91.242.xxx.xxx")
rThread = threading.Thread(target=cli.run, args=(id,))
rThread.daemon = True
rThread.start()
print("Connected to server")
The only thing that outputs is Connecting to server
I am not sure what I am doing wrong or what to do to fix this
My ISP uses CGNat and I just had to call them to tell them that I need a public IP and they gladly did it for me.

A receiver that can receive both TCP images and UDP texts

I'm new to socket programming . I've implemented 2 separated codes on the same host. One of them is supposed to receive images using TCP protocol and the second one is supposed to receive text messages through UDP protocol. Both of them are working fine separately. Here are the codes:
Image receiver (TCP):
from __future__ import print_function
import socket
from struct import unpack
import Queue
from PIL import Image
HOST = '10.0.0.1'
PORT = 12345
BUFSIZE = 4096
q = Queue.Queue()
class Receiver:
''' Buffer binary data from socket conn '''
def __init__(self, conn):
self.conn = conn
self.buff = bytearray()
def get(self, size):
''' Get size bytes from the buffer, reading
from conn when necessary
'''
while len(self.buff) < size:
data = self.conn.recv(BUFSIZE)
if not data:
break
self.buff.extend(data)
# Extract the desired bytes
result = self.buff[:size]
# and remove them from the buffer
del self.buff[:size]
return bytes(result)
def save(self, fname):
''' Save the remaining bytes to file fname '''
with open(fname, 'wb') as f:
if self.buff:
f.write(bytes(self.buff))
while True:
data = self.conn.recv(BUFSIZE)
if not data:
break
f.write(data)
def main():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
sock.bind((HOST, PORT))
except socket.error as err:
print('Bind failed', err)
return
sock.listen(1)
print('Socket now listening at', HOST, PORT)
try:
while True:
conn, addr = sock.accept()
print('Connected with', *addr)
# Create a buffer for this connection
receiver = Receiver(conn)
# Get the length of the file name
name_size = unpack('B', receiver.get(1))[0]
# Get the file name itself
name = receiver.get(name_size).decode()
q.put(name)
print('name', name)
# Save the file
receiver.save(name)
conn.close()
print('saved\n')
# Hit Break / Ctrl-C to exit
except KeyboardInterrupt:
print('\nClosing')
sock.close()
if __name__ == '__main__':
main()
Text receiver (UDP):
import socket
UDP_IP = "10.0.0.1"
UDP_PORT = 5005
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
sock.bind((UDP_IP, UDP_PORT))
while True:
data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
print "received message:", data
Now my question is: How can I merge these 2 codes? I don't want to open 2 separate consoles for each of them and I want one code instead of two. Is it possible?
I tried the solution which was provided in the comment and here is the code:
from __future__ import print_function
from select import select
import socket
from struct import unpack
host = '10.0.0.2'
port = 5005
size = 8000
backlog = 5
class Receiver:
''' Buffer binary data from socket conn '''
def __init__(self, conn):
self.conn = conn
self.buff = bytearray()
def get(self, size):
''' Get size bytes from the buffer, reading
from conn when necessary
'''
while len(self.buff) < size:
data = self.conn.recv(BUFSIZE)
if not data:
break
self.buff.extend(data)
# Extract the desired bytes
result = self.buff[:size]
# and remove them from the buffer
del self.buff[:size]
return bytes(result)
def save(self, fname):
''' Save the remaining bytes to file fname '''
with open(fname, 'wb') as f:
if self.buff:
f.write(bytes(self.buff))
while True:
data = self.conn.recv(BUFSIZE)
if not data:
break
f.write(data)
def read_tcp(s):
conn, addr = s.accept()
print('Connected with', *addr)
# Create a buffer for this connection
receiver = Receiver(conn)
# Get the length of the file name
name_size = unpack('B', receiver.get(1))[0]
name = receiver.get(name_size).decode()
print('name', name)
# Save the file
receiver.save(name)
conn.close()
print('saved\n')
def read_udp(s):
data,addr = s.recvfrom(8000)
print("Recv UDP:'%s'" % data)
def run():
# create tcp socket
tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcp.bind((host,port))
tcp.listen(1)
# create udp socket
udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
udp.bind((host,port))
input = [tcp,udp]
while True:
inputready,outputready,exceptready = select(input,[],[])
for s in inputready:
if s == tcp:
read_tcp(s)
elif s == udp:
read_udp(s)
else:
print("unknown socket:", s)
if __name__ == '__main__':
run()
but I don't receive any UDP or TCP packet now and it doesn't seem to work for me.
Short answer yes, but you will need to implement multithreading for this. For instance, your program will spawn two threads, one for TCP sockets and other for UDP.

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