How to handle client shutdown using threads in python? - python

I am new to Socket programming, My use case is to add shutdown message in my code that if one of the clients goes off or interrupted or killed then my server easily update the count or kill that thread.
import socket
import SSL
import testThread
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.verify_mode = ssl.CERT_REQUIRED
context.load_cert_chain(certfile=self.server_cert, keyfile=self.server_key)
context.load_verify_locations(cafile=self.ca_cert)
# to add threads
t = []
# to store addresses
totalAddress = []
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((self.TCP_IP, self.TCP_Port))
s.listen(4)
while True:
print "Waiting for connections from TCP clients..."
(conn, (ip, port)) = tcpServer.accept()
print("Client connected: {}:{}".format(ip, port))
conn = context.wrap_socket(conn, server_side=True)
newthread = testThread.TestThread(ip, port, conn)
newthread.start()
t.append(newthread)
totalAddress.append((ip,port))
count = newthread.count() -1
print "[ACTIVE CONNECTIONS] {} and number of clients running {}".format(totalAddress, count)
I have created count() in testThread.py file.
import threading
from datetime import datetime
import time
class TestThread(Thread):
def __init__(self, ip, port, conn):
# import pdb; pdb.set_trace()
Thread.__init__(self)
self.ip = ip
self.port = port
self.conn = conn
print "[+] New server socket thread started for " + ip + ":" + str(port)
")
def run(self):
while True:
data = self.conn.recv(2048)
now = datetime.now()
data = str(now) + " - " + data
#print "Server received data:", data
f = open("demofile.txt", "a")
f.write(data)
f.close()
Please excuse me if there is an error in the code. :)

Related

Getting a TimeOut Error when trying to run a python code that transfers files from EC2 to Local

This is the code on the AWS EC2 instance:
import socket
from threading import Thread
from socketserver import ThreadingMixIn
TCP_IP = 'localhost'
TCP_PORT = 9001
BUFFER_SIZE = 1024
class ClientThread(Thread):
def __init__(self,ip,port,sock):
Thread.__init__(self)
self.ip = ip
self.port = port
self.sock = sock
print (" New thread started for "+ip+":"+str(port))
def run(self):
filename='mytext.txt'
f = open(filename,'rb')
while True:
l = f.read(BUFFER_SIZE)
while (l):
self.sock.send(l)
#print('Sent ',repr(l))
l = f.read(BUFFER_SIZE)
if not l:
f.close()
self.sock.close()
break
tcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpsock.bind((TCP_IP, TCP_PORT))
threads = []
while True:
tcpsock.listen(5)
print ("Waiting for incoming connections...")
(conn, (ip,port)) = tcpsock.accept()
print ('Got connection from ', (ip,port))
newthread = ClientThread(ip,port,conn)
newthread.start()
threads.append(newthread)
for t in threads:
t.join()
And this is the code on my local machine:
import socket
import time
#TCP_IP = 'localhost'
TCP_IP = 'ip-ec2-instance'
TCP_PORT = 60001
BUFFER_SIZE = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
clock_start = time.clock()
time_start = time.time()
with open('received_file', 'wb') as f:
print ('file opened')
while True:
#print('receiving data...')
data = s.recv(1024)
#print('data=%s', (data))
if not data:
f.close()
print ('file close()')
break
# write data to a file
f.write(data)
print('Successfully get the file')
s.close()
print('connection closed')
clock_end = time.clock()
time_end = time.time()
duration_clock = clock_end - clock_start
print ('clock: start = ',clock_start, ' end = ',clock_end)
print ('clock: duration_clock = ', duration_clock)
duration_time = time_end - time_start
print ('time: start = ',time_start, ' end = ',time_end)
print ('time: duration_time = ', duration_time)
Now, the code on the EC2 instance seems to run fine and waits for a connection, but the code on my local machine gives me the error mentioned below when I try running it with the public IP of the EC2 instance:
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
I can't figure out how to fix this.

How to limit the amount of requests per ip connection in socket programming in python?

I'm developing a Firewall for math server(Tcp server using sockets) in python to prevent the server from Distributed denial of service attack as an mini project.This is my code
import socket
import re
from subprocess import Popen, STDOUT, PIPE
from threading import Thread
def start_new_math_thread(conn, addr):
t = MathServerCommunicationThread(conn, addr)
t.start()
class ProcessOutputThread(Thread): #OOPS
def __init__(self, proc, conn):
Thread.__init__(self)
self.proc = proc
self.conn = conn
def run(self):
while not self.proc.stdout.closed and not self.conn._closed:
try:
self.conn.sendall(self.proc.stdout.readline())
except:
pass
class MathServerCommunicationThread(Thread):
def __init__(self, conn, addr):
Thread.__init__(self)
self.conn = conn
self.addr = addr
def run(self):
self.conn.sendall("Simple Math Server developed by LAHTP Version-2.o ('integrated with Firewall' ) \n\nGive any math expressions, and I will answer you...\U0001F609 \n\n$ ".encode())
p = Popen(['bc'], stdout=PIPE, stdin=PIPE, stderr=STDOUT)
output = ProcessOutputThread(p, self.conn)
output.start()
while not p.stdout.closed or not self.conn._closed:
try:
data = self.conn.recv(1024)
if not data:
break
else:
try:
data = data.decode()
query = data.strip()
if query == 'quit' or query == 'exit':
print("{} disconnected...!".format(addr[0]))
con.remove(addr[0])
p.communicate(query.encode(), timeout=1)
if p.poll() is not None:
break
query = query + '\n'
p.stdin.write(query.encode())
p.stdin.flush()
if not re.match("^[0-9|+|-|*|/|^|=]{1,15}$",query):
conn.send(b"Only Integers are allowed & it should range between 0to15 digits\n")
self.conn.close()
print ("{} is trying to exploit the resources so the connection is closed.".format(addr[0]))
con.remove(addr[0])
else:
pass
except:
pass
except:
pass
self.conn.close()
HOST = ''
PORT = 8877
con=[]
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
print("Server initialized\n Waiting for the incoming connections...")
s.listen()
while True:
conn, addr = s.accept()
start_new_math_thread(conn, addr)
if addr[0] in con:
print("connection rejected from {}:{}".format(addr[0],addr[1]))
conn.close()
else:
con.append(addr[0])
print("connection accepted from {}:{}".format(addr[0],addr[1]))
i want to limit the amount of request from user by giving the limitaion to the requests per ip connection per minute(in socket programming). I searched many sources to implement this, but i am unable to find this, Is this possible?if yes,what am i should do?

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.

Server Loop Using Python Sockets and Threading module

I am making server-client communication in python using sockets and threading module. I connect client to server, send some data, receive some data, but the problem is, I can send only two messages. After those, the server is not reciving my packets. Can someone tell me what's wrong? Thanks in advance.
Server.py:
import socket
from threading import Thread
class Server:
def __init__(self):
self.host = '127.0.0.1'
self.port = 9999
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind((self.host, self.port))
self.server.listen(5)
self.threads = []
self.listen_for_clients()
def listen_for_clients(self):
print('Listening...')
while True:
client, addr = self.server.accept()
print('Accepted Connection from: '+str(addr[0])+':'+str(addr[1]))
self.threads.append(Thread(target=self.handle_client, args=(client, addr)))
for thread in self.threads:
thread.start()
def handle_client(self, client_socket, address):
client_socket.send('Welcome to server'.encode())
size = 1024
while True:
message = client_socket.recv(size)
if message.decode() == 'q^':
print('Received request for exit from: '+str(address[0])+':'+str(address[1]))
break
else:
print('Received: '+message.decode()+' from: '+str(address[0])+':'+str(address[1]))
client_socket.send('Received request for exit. Deleted from server threads'.encode())
client_socket.close()
if __name__=="__main__":
main = Server()
Client.py
import socket
import sys, time
def main():
target_host = '127.0.0.1'
target_port = 9999
try:
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
print('Could not create a socket')
time.sleep(1)
sys.exit()
try:
client.connect((target_host, target_port))
except socket.error:
print('Could not connect to server')
time.sleep(1)
sys.exit()
while True:
data = input()
client.send(data.encode())
message = client.recv(4096)
print('[+] Received: '+ message.decode())
main()
You have to send exit message 'q^' to client too to close client.
Warning:
Using Unicode as encoding for string is not recommended in socket. A partial Unicode character may be received in server/client resulting in UnicodeDecodeError being raised.
Code for server using threads is:
server.py:
import socket
from threading import Thread
class Server:
def __init__(self, host, port):
self.host = host
self.port = port
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind((self.host, self.port))
self.server.listen(5)
def listen_for_clients(self):
print('Listening...')
while True:
client, addr = self.server.accept()
print(
'Accepted Connection from: ' + str(addr[0]) + ':' + str(addr[1])
)
Thread(target=self.handle_client, args=(client, addr)).start()
def handle_client(self, client_socket, address):
size = 1024
while True:
try:
data = client_socket.recv(size)
if 'q^' in data.decode():
print('Received request for exit from: ' + str(
address[0]) + ':' + str(address[1]))
break
else:
# send getting after receiving from client
client_socket.sendall('Welcome to server'.encode())
print('Received: ' + data.decode() + ' from: ' + str(
address[0]) + ':' + str(address[1]))
except socket.error:
client_socket.close()
return False
client_socket.sendall(
'Received request for exit. Deleted from server threads'.encode()
)
# send quit message to client too
client_socket.sendall(
'q^'.encode()
)
client_socket.close()
if __name__ == "__main__":
host = '127.0.0.1'
port = 9999
main = Server(host, port)
# start listening for clients
main.listen_for_clients()
client.py:
import socket
import sys, time
def main():
target_host = '127.0.0.1'
target_port = 9999
try:
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
print('Could not create a socket')
time.sleep(1)
sys.exit()
try:
client.connect((target_host, target_port))
except socket.error:
print('Could not connect to server')
time.sleep(1)
sys.exit()
online = True
while online:
data = input()
client.sendall(data.encode())
while True:
message = client.recv(4096)
if 'q^' in message.decode():
client.close()
online = False
break
print('[+] Received: ' + message.decode())
break # stop receiving
# start client
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