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()
Related
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.
I have made a multithreaded Python socket server.
It supports multiple socket client connections.
My code is:
import socket
from _thread import *
def multi_threaded_client(connection):
response = ''
while True:
data = connection.recv(10000000)
response += data.decode('utf-8')
if not data:
print(response)
break
connection.send(bytes(some_function_name(response), "utf-8"))
connection.close()
class socketserver:
def __init__(self, address='', port=9090):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.address = address
self.port = port
self.sock.bind((self.address, self.port))
self.cummdata = ''
def recvmsg(self):
self.sock.listen(65535)
self.conn, self.addr = self.sock.accept()
print('connected to', self.addr)
self.cummdata = ''
start_new_thread(multi_threaded_client, (self.conn, ))
return self.cummdata
def __del__(self):
self.sock.close()
serv = socketserver('127.0.0.1', 9090)
print('Socket Created at {}. Waiting for client..'.format(serv.sock.getsockname()))
while True:
msg = serv.recvmsg()
I also want the server to detect if any new client is connected to /disconnected from it.
Once all the clients are disconnected from it, I want the server to be closed on its own.
I could not figure this out
(I have the following code in which I would like to implement a server-side application and to send clients a response:
class client(Thread):
def __init__(self, socket, address):
Thread.__init__(self)
self.sock = socket
self.addr = address
self.start()
def run(self):
request = ''
while 1:
data = self.sock.recv(1024).decode() # The program hangs here with large message
if not data:
break
request += data
print(request, self.addr[1], self.addr[0]))
message = "test"
self.sock.send(message.encode())
def init_server():
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind((host, int(port)))
serversocket.listen(5)
while 1:
clients, address = serversocket.accept()
client(clients, address)
return
Now I write a simple client:
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('localhost', 8000))
client_socket.send(message)
request = ''
while 1:
data = client_socket.recv(2048).decode()
if not data:
break
request += data
print(request)
client_socket.close()
The problem now is that the server hangs in recv with a large message. How can I solve it?
Your client socket and server socket are different sockets.
You can get server info using the serversocket object the same way you try self.sock.
I would recommend parsing serversocket as a third argument into your client class, and then using it within the class like so:
class client(Thread):
def __init__(self, socket, address, server):
Thread.__init__(self)
self.sock = socket
self.addr = address
self.server = server
self.start()
def run(self):
request=''
while 1:
data=self.sock.recv(1024).decode()
if not data:
break
request+=data
print(request, self.server.getsockname()[1], self.server.getsockname()[0]))
def init_server():
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind((host, int(port)))
serversocket.listen(5)
while 1:
clients, address = serversocket.accept()
client(clients, address, serversocket)
return
That should output the server information.
If you wanted the client information, it's parsed in the 'address' as a tuple, you can see the remote IP address and the socket port used to communicate on (not the open port).
According to the code on the book, I used TCPServer to create a TCP server and overrite the handle().
After build the connection, the server will print 'connected:' and client address.
but when I self.wfile.write() to send the data, either the server and client can't receive the data.
code of server:
from socketserver import (TCPServer as TCP, StreamRequestHandler as SRH)
HOST = ''
PORT = 1235
ADDR = (HOST, PORT)
class MyRequestHandler(SRH):
def handle(self):
print('connected:', self.client_address)
self.wfile.write('kkk'.encode('utf-8'))
tcpServ = TCP(ADDR, MyRequestHandler)
print('waiting for connection...')
tcpServ.serve_forever()
code of client:
from socket import *
HOST = 'localhost'
PORT = 1235
BUFSIZE = 1024
ADDR = (HOST, PORT)
while True:
tcpCliSock = socket(AF_INET, SOCK_STREAM)
tcpCliSock.connect(ADDR)
data = input('>')
if not data:
break
tcpCliSock.send(data.encode("utf-8"))
data = tcpCliSock.recv(BUFSIZE).decode("utf-8")
if not data:
break
print(data)
tcpCliSock.close()
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()