I want to customize a addon to filter the specified HOST request, and can send some socket messages unidirectionally after each successful filtering, but every time receiving a socket message in another process will generate a delay of about 0.15s.
Is there a better way please, or where is the problem with my code?
System Information:
Mitmproxy: 6.0.2
List item
Python: 3.8.0
Platform: macOS-12.2.1
The main code of the addon:
class MyAddon:
#script.concurrent
def request(self, flow: http.HTTPFlow):
...
#script.concurrent
def response(self, flow: http.HTTPFlow):
msg = ... #Create a message
if flow.request.host in HOST_LIST:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.connect((HOST, PORT))
s.send(msg)
This is the server process code:
class Server:
def __init__(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
port = 9999
self.sock.bind(('127.0.0.1', port))
self.sock.listen(10)
self.sever_th = threading.Thread(target=self.tcp_server)
self.sever_th.start()
def tcp_server(self):
while True:
t0 = time.time()
conn, addr = self.sock.accept() #There is a delay of about 0.15s
print('%0.5f' % (time.time() - t0))
with conn:
buff = b''
while True:
data = conn.recv(1024)
if data == b'':
print(buff)
break
else:
buff += data
if __name__ == "__main__":
server = Server()
I have tried sending messages using one socket, but the delay effect is still the same.
I use the Socket to send multiple groups of the same message without the Addon, and there is no such high delay.The bytes of each message sent are about 600 Bytes.
Related
A quite basic problem, but I can't find my mistake. I bascially used this tutorial code to implement my own client-server program: Client sends some data, the server displays it (instead of echoing data like in the tutorial)
The echoing tutorial code works, but my adjusted code to print data on the server doesn't. I added some delimiter mechanism to detect the entire message. My code:
Server.py:
class ThreadedServer:
def __init__(self, host, port):
self.host = host
self.port = port
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.bind((self.host, self.port))
print("Server bound on Port "+str(port))
def listen(self):
self.sock.listen(5)
while True:
print("Waiting for incoming connections...")
client, address = self.sock.accept()
client.settimeout(60)
print("Starting Working thread.")
threading.Thread(target=self.listenToClientDelimiter, args=(client, address)).start()
def listenToClientDelimiter(self, client, address):
print("Connect to client "+address)
length = None
buffer = ""
while True:
data = client.recv(1024)
print("Received raw data: "+str(data))
if not data:
break # connection closed
buffer += data
while True:
if length is None:
if LENGTH_DELIMITER not in buffer:
break # delimiter not found, wait for next data package
length_str, _, buffer = buffer.partition(LENGTH_DELIMITER)
length = int(length_str)
if len(buffer) < length:
break # wait until full length got received before we proceed
message = buffer[:length]
buffer = buffer[length:]
length = None
# PROCESS MESSAGE HERE
print(message)
client.close()
if __name__ == "__main__":
ThreadedServer('', 65432).listen()
Client.py:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect(("127.0.0.1", 65432))
connect_user_cmd = "18:CONNECT_USER;Peter"
print("Trying to send data: "+connect_user_cmd.decode())
print(s.send(connect_user_cmd))
I run the server, then the client. The output from the server:
Server bound on Port 65432
Waiting for incoming connections...
As you see, I expect some log messages and of course my sent message. The client outputs this:
Trying to send data: 18:CONNECT_USER;Peter
21
Process finished with exit code 0
This gets outputted from the client even when I don't start the server. The weird thing is that the echoing part did indeed work. Could someone hint me into the right direction? Thank you!
I want my server to send the string "con-res 0xFE" to reset the server if it has been more than 4 seconds since a new message was sent by the client.
I have tried to puzzle around with time.time() but in the end I can't figure out how to register a time for each message it self.
Client:
import socket
# Create a UDP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_address = ('localhost', 12000)
number_of_packages = 0;
try:
while True:
message = input("Write something: ")
# Send data
sent = sock.sendto(message.encode(), server_address)
number_of_packages +=1
if (number_of_packages > 25):
print("Too many packages - closing socket")
socket.close()
# Receive response
data, server = sock.recvfrom(4096)
print('client received: ', data.decode())
if data.decode()=="con-res 0xFE":
print("conn reset!")
sent = sock.sendto("con-res 0xFFDDDDD".encode(), server_address)
finally:
sock.close()
My server:
# Create a UDP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Bind the socket to the port
server_address = ('localhost', 12000)
sock.bind(server_address)
count_message = 0
while True:
data, address = sock.recvfrom(4096)
#check 4 seconds since last message
if data:
start_time = time.time()
sent = sock.sendto("ok".encode(), address)
The above code incidents might be wrong as I had difficulties make sure it looked as code here on Stackoverflow. However the above code is working as it should.
I am trying to send a TCP message at random time, depending on when the user input is received, to one of several clients from which I am receiving data on a thread for each client.
I am storing the IP of each client inside an SQL database and I decide to which IP i want to send data based on user input. How should I approach sending a message to a specific client ? I don't know how I can gain access over each socket connection and use it to send messages.
Any device, links of examples, or code snippets are greatly welcome.
This is the server code that I have so far :
import socket
import threading
from database import Database
d = Database()
def Read_RFID_tag():
while True:
receiveID = raw_input("tag input : ")
d.updateTable(receiveID, 1);
print(receiveID)
class ThreadedServer(object):
def __init__(self, host, port):
self.host = host
self.port = port
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.bind((self.host, self.port))
def listen(self):
self.sock.listen(5)
while True:
client, address = self.sock.accept()
print("new client")
client.settimeout(60)
threading.Thread(target = self.listenToClient,args = (client,address)).start()
def listenToClient(self, client, address):
size = 1024
while True:
query_result = d.existsWashedInTable(address)
try:
data = client.recv(size)
if data:
# Set the response to echo back the received data
print(data)
response = data
d.addEntryToTable(response,address, 0)
client.send(response)
else:
raise error('Client disconnected')
except:
client.close()
return False
if __name__ == "__main__":
port_num = 5005
d.createTable()
threading.Thread(target=Read_RFID_tag).start()
ThreadedServer('',port_num).listen()
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'm am trying to write a client program in Python that can send and receive from the same socket, but it is always giving me the same error which address is already in use. Here is the function I'm trying to write.
def Login():
username=raw_input()
password=raw_input()
message=raw_input()
array=[username,password,message]
TCP_IP = '127.0.0.1'
TCP_PORT = 5563
BUFFER_SIZE = 1024 # Normally 1024, but we want fast response
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((TCP_IP, TCP_PORT))
array_string=pickle.dumps(array)
sock.send(array_string)
sock.close()
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((TCP_IP, TCP_PORT))
sock.listen(1)
conn, info = sock.accept()
while 1:
data = serverSocket.recv(1024)
if not data:break
conn.send(data)
conn.close()
There is a bunch of truly newbie errors here.
You can't ever connect a TCP socket to itself. There must be two different sockets.
If you really want to get the data you sent earlier at a listening socket, this listening socket must be created, bound and configured to listen before the client side connects (or, at least, in parallel to this connect attempt, in a few seconds, so the connect attempt will try - but this very likely won't work on localhost).
You can't wait on connect and on accept in the same thread if both are blocking. The simplest approach is to separate the client side and the server side to 2 different programs and run them manually in parallel. Then, after successful debugging, you will be able to do this in different threads of the same process, or using an event-driven engine.
While you may not be able to connect a socket to itself to send and receive data, you might be able to learn from the following example inspired by your code that attempts to do something similar.
import _thread
import pickle
import socket
import time
def main():
"""Run a server in a thread and start a client to talk to it."""
_thread.start_new_thread(run_server, ('', 5563))
run_client('localhost', 5563)
def run_server(host, port):
"""Handle all incoming connections by spawning worker threads."""
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port))
server.listen(5)
while True:
_thread.start_new_thread(handle_connection, server.accept())
def handle_connection(client, address):
"""Answer an incoming question from the connected client."""
print('Incoming connection from', address)
client.settimeout(0.1)
data = recvall(client)
client.shutdown(socket.SHUT_RD)
question = pickle.loads(data)
answer = '''len(username) = {}
len(password) = {}
len(message) = {}'''.format(*map(len, question))
client.sendall(answer.encode())
client.shutdown(socket.SHUT_WR)
client.close()
print('Finished with', address)
def recvall(connection):
"""Receive all data from a socket and return as a bytes object."""
buffer = bytearray()
while True:
try:
data = connection.recv(1 << 12)
except socket.timeout:
pass
else:
if data:
buffer.extend(data)
else:
return bytes(buffer)
def run_client(host, port):
"""Collect information from question and display returned answer."""
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
time.sleep(0.1) # wait for server to start listening for clients
client.connect((host, port))
time.sleep(0.1) # wait for handler thread to display connection
username = input('Username: ')
password = input('Password: ')
message = input('Message: ')
question = pickle.dumps((username, password, message))
client.sendall(question)
client.shutdown(socket.SHUT_WR)
answer = recvall(client)
client.shutdown(socket.SHUT_RD)
client.close()
print(answer.decode())
time.sleep(0.1) # wait for handler to cleanly terminate execution
if __name__ == '__main__':
main()