Why does async socket cannot accept 1 more clients on python3? - python

I tried to make async socket core for my private server for game. This works, but don't accept more than 1 client. 2 clients trying to connect, but second client cannot do this, only when first will disconnect.
import asyncio, socket, time
class Server:
def __init__(self, port: int):
self.server = socket.socket()
self.port = port
async def start(self):
self.server.bind(("0.0.0.0", self.port))
self.server.listen()
print(f"Server started on {self.port}!")
while True:
session, ip = self.server.accept()
print(f"{ip[0]} connected!")
await Connection(session, ip[0]).messaging()
class Connection:
def __init__(self, session, ip):
self.session = session
self.ip = ip
def receive(self, session, lens):
data = b""
while len(data) < lens:
s = session.recv(lens)
if not s:
s += 0
break
data += s
return data
async def messaging(self):
last = int(time.time())
while True:
try:
header = self.session.recv(7)
if len(header) > 0:
last = int(time.time())
mtype = int.from_bytes(header[:2], "big")
mlen = int.from_bytes(header[2:5], "big")
mdata = self.receive(self.session, mlen)
print(f"[C] {mtype} from {self.ip}")
if int(time.time()) - last > 7:
break
except(ConnectionAbortedError, ConnectionResetError, ConnectionRefusedError, TimeoutError, OSError):
break
self.session.close()
print(f"{self.ip} disconnected!")
asyncio.run(Server(9339).start())
I tried to use module select but this has laggy disconnect.

Related

How to put packet in socket

How to put packet in socket, when I use socket.recv? I made my TCP server to client network. But in the code, I want to put packet in self.soc.recv(1024). How can I put the packet in socket?
Here's my code
#서버 코드
import threading, socket
class Room: #채팅방
def __init__(self):
self.clients = []#접속한 클라이언트를 담당하는 ChatClient 객체 저장
def addClient(self, c):#클라이언트 하나를 채팅방에 추가
self.clients.append(c)
def delClent(self, c):#클라이언트 하나를 채팅방에서 삭제
self.clients.remove(c)
def sendAllClients(self, msg):
for c in self.clients:
c.sendMsg(msg)
class ChatClient:#텔레 마케터: 클라이언트 1명이 전송한 메시지를 받고, 받은 메시지를 다시 되돌려줌
def __init__(self, id, soc, r):
self.id = id #클라이언트 id
self.soc = soc #담당 클라이언트와 1:1 통신할 소켓
self.room = r #채팅방 객체
def recvMsg(self):
while True:
data = self.soc.recv(1024)
msg = data.decode()
if msg == '/stop':
self.sendMsg(msg) # 클라이언트쪽의 리시브 쓰레드 종료하라고..
print(self.id,'님 퇴장')
break
msg = self.id+': ' + msg
self.room.sendAllClients(msg)
self.room.delClent(self)
self.room.sendAllClients(self.id+'님이 퇴장하셨습니다.')
def sendMsg(self, msg): #담당한 클라이언트 1명에게만 메시지 전송
self.soc.sendall(msg.encode(encoding='utf-8'))
def run(self):
t = threading.Thread(target=self.recvMsg, args=())
t.start()
class ServerMain:
ip = '192.168.55.232'
port = 2500
def __init__(self):
self.room = Room()
self.server_soc = None
def open(self):
self.server_soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_soc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server_soc.bind((ServerMain.ip, ServerMain.port))
self.server_soc.listen()
def run(self):
self.open()
print('채팅 서버 시작')
while True:
c_soc, addr = self.server_soc.accept()
print(addr)
msg = '사용할 id:'
c_soc.sendall(msg.encode(encoding='utf-8'))
msg = c_soc.recv(1024)
id = msg.decode()
cc = ChatClient(id, c_soc, self.room)
self.room.addClient(cc)
cc.run()
print('클라이언트', id, '채팅 시작')
def main():
server = ServerMain()
server.run()
main()
I got my packet by wireshark, and I want put packet in soket.recv(). Is any solution that I can get?

python proxy script have some problems

i was tried to use asyncio and threading libraries in different scripts. but threading will cause this error in high connections:
filedescriptor out of range in select()
my source that cause this error:
try:
reader, _, _ = select.select([socket_src, socket_dst], [], [], 1)
except select.error as err:
error("Select failed", err)
i tried to increase fd limit but it not fix this error.
and in asyncio library:
after run script everything is ok.
after 20 minutes of running script, users will connect to proxy after about 1 min of send request
and any user can not connect to proxy after 1 hour...
my source:
import socket
import asyncio
import aiosocks
from struct import pack, unpack
class Client(asyncio.Protocol):
def connection_made(self, transport):
self.transport = transport
self.server_transport = None
def data_received(self, data):
# print('recv:', repr(data))
self.server_transport.write(data)
def connection_lost(self, *args):
self.server_transport.close()
class Server(asyncio.Protocol):
INIT, HOST, DATA = 0, 1, 2
def connection_made(self, transport):
print('from:', transport.get_extra_info('peername'))
self.transport = transport
self.state = self.INIT
def connection_lost(self, exc):
self.transport.close()
def data_received(self, data):
# print('send:', repr(data))
if self.state == self.INIT:
assert data[0] == 0x05
self.transport.write(pack('!BB', 0x05, 0x00)) # no auth
self.state = self.HOST
elif self.state == self.HOST:
ver, cmd, rsv, atype = data[:4]
assert ver == 0x05 and cmd == 0x01
if atype == 3: # domain
length = data[4]
hostname, nxt = data[5:5+length], 5+length
elif atype == 1: # ipv4
hostname, nxt = socket.inet_ntop(socket.AF_INET, data[4:8]), 8
elif atype == 4: # ipv6
hostname, nxt = socket.inet_ntop(socket.AF_INET6, data[4:20]), 20
port = unpack('!H', data[nxt:nxt+2])[0]
print('to:', hostname, port)
asyncio.ensure_future(self.connect(hostname, port))
self.state = self.DATA
elif self.state == self.DATA:
self.client_transport.write(data)
async def connect(self, hostname, port):
loop = asyncio.get_event_loop()
socks5_addr = aiosocks.Socks5Addr('127.0.0.1', 1080)
dst = (hostname, port)
transport, client = await aiosocks.create_connection(Client, proxy=socks5_addr, proxy_auth=None, dst=dst)
client.server_transport = self.transport
self.client_transport = transport
hostip, port = transport.get_extra_info('sockname')
host = unpack("!I", socket.inet_aton(hostip))[0]
self.transport.write(
pack('!BBBBIH', 0x05, 0x00, 0x00, 0x01, host, port))
if __name__ == '__main__':
loop = asyncio.get_event_loop()
srv = loop.create_server(Server, 'localhost', 8000)
loop.run_until_complete(srv)
loop.run_forever()
what should i do to fix at least one of this problems?
if you know any other libraries, please say me.
thanks

Mouse remote control

Trying to implement some kind of synergy on python using PyAutoGui and socket communication.
The idea is to control mouse and keyboard of another computer on LAN by using mouse/keyboard of a server computer.
By now it's only mouse movement implementaion.
Here are some classes:
Server part:
class Server:
def __init__(self):
self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.ip = get_ip()
self.port = 3000
self.transfer_mod = False
self.client_address = ""
def start(self):
print("Started server with ip: {}".format(self.ip))
self.s.bind((self.ip, self.port))
self.get_connection()
def get_connection(self):
print("Waiting for connection...")
while True:
request, self.client_address = self.s.recvfrom(4096)
if request:
self.s.sendto(request, self.client_address)
print("{} connected!".format(self.client_address))
break
def enable_transfer(self):
print("Transfer to {} enabled".format(self.client_address))
self.transfer_mod = True
transfer_thread = threading.Thread(target=self.transfer_mouse)
transfer_thread.start()
def disable_transfer(self):
print("Transfer to {} disabled".format(self.client_address))
self.transfer_mod = False
def transfer_mouse(self):
previous_pos = (-1, -1)
while self.transfer_mod:
pos = pyautogui.position()
if pos != previous_pos:
data = pickle.dumps(pos)
self.s.sendto(data, self.client_address)
sleep(0.1)
previous_pos = pos
def close(self):
self.disable_transfer()
self.s.close()
Client part:
class Client:
def __init__(self):
self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.port = 3000
self.connection = False
def connect(self, server_ip):
request = bytes("Request","utf-8")
self.s.sendto(request, (server_ip, self.port))
received, address = self.s.recvfrom(4096)
if received == request:
print("Connected to {}".format(server_ip))
self.connection = True
threading.Thread(target=self.receive_data).start()
def receive_data(self):
while self.connection:
data, server = self.s.recvfrom(4096)
pos = pickle.loads(data)
self.control_mouse(pos)
def disconnect(self):
print("Disconnected from the server")
self.connection = False
def control_mouse(self, position):
pyautogui.moveTo(position[0], position[1])
def close(self):
self.disconnect()
self.s.close()
So, the problem of that is the speed of mouse movement on client computer is so low. It seems there are too many exceed packets or something like that. So, the question itself: Is it a good way of implementing this idea, if yes, what's the problem of that script, if no, any advises on how to do it more properly?

can python asyncio data_received receive all data which client sent

I am learning python asyncio module and try to write a socks5 server with it. Python docs said:
Called when some data is received. data is a non-empty bytes object
containing the incoming data.
I wonder when client sends 2 bytes data, will data_received(self, data) just receive 1 byte not 2 bytes when it called and the rest 1 byte will call data_received(self, data) again?
#!/usr/bin/env python3
import asyncio
import logging
import socket
import struct
logging.basicConfig(level=logging.DEBUG,
format='{asctime} {levelname} {message}',
datefmt='%Y-%m-%d %H:%M:%S',
style='{')
class Remote(asyncio.Protocol):
def connection_made(self, transport):
self.transport = transport
self.server_transport = None
def data_received(self, data):
self.server_transport.write(data)
class Server(asyncio.Protocol):
INIT, REQUEST, REPLY = 0, 1, 2
def connection_made(self, transport):
client_info = transport.get_extra_info('peername')
logging.info('connect from {}'.format(client_info))
self.transport = transport
self.state = self.INIT
def data_received(self, data):
if self.state == self.INIT:
if data[0] == 5:
amount = data[1] # Authentication amount
if 0 in data[2:]:
self.transport.write(b'\x05\x00')
self.state = self.REQUEST
else:
self.eof_received()
else:
self.eof_received()
elif self.state == self.REQUEST:
ver, cmd, rsv, addr_type = data[:4]
logging.info('addr type: {}'.format(addr_type))
if addr_type == 1: # ipv4
addr = socket.inet_ntoa(data[4:8])
elif addr_type == 3:
addr_len = data[4]
addr = data[5:5+addr_len]
else:
data = b'\x05\x08\x00\x01'
data += socket.inet_aton('0.0.0.0') + struct.pack('>H', 0)
self.transport.write(data)
logging.error('not support addr type')
self.eof_received()
port = struct.unpack('>H', data[-2:])[0]
logging.info('target: {}:{}'.format(addr, port))
asyncio.ensure_future(self.remote(addr, port))
self.state = self.REPLY
elif self.state == self.REPLY:
logging.info('start relay')
self.remote_transport.write(data)
async def remote(self, addr, port):
loop = asyncio.get_event_loop()
transport, _remote = await loop.create_connection(Remote, addr, port)
_remote.server_transport = self.transport
self.remote_transport = transport
bind_addr, bind_port = transport.get_extra_info('sockname')
data = b'\x05\x00\x00\x01'
data += socket.inet_aton(bind_addr) + struct.pack('>H', bind_port)
self.transport.write(data)
if __name__ == '__main__':
loop = asyncio.get_event_loop()
server = loop.create_server(Server, '127.0.0.2', 1089)
loop.run_until_complete(server)
try:
loop.run_forever()
except KeyboardInterrupt:
server.close()
loop.run_until_complete(server.close())
loop.close()
no, data_received will receive as many bytes as are already received by the server. If you need to receive the first 3 bytes to handle the request, then you should implement some buffering in your Protocol to allow you to wait for the rest of the request to arrive before continuing.
It would typically look like this:
def __init__(self, …):
self._buffer = bytearray()
…
def data_received(self, data):
self._buffer += data
if self.state == self.INIT:
# here we need at least 3 bytes.
# if we don't have enough data yet, just wait for the next `data_received` call
if len(self._buffer) < 3:
return
header, self._buffer = self._buffer[:2], self._buffer[2:]
# parse authentication header, switch the state to REQUEST
elif self.state == self.REQUEST:
…

Python Socket - Can't connect a second time

I have set up a socket server with a client and a host.
It works fine until the client has disconnected, with both .shutdown() and .close().
When I then launch the client again, it can't connect.
I presume this is not because of how I've written my code but rather what I haven't written.
How do I make the server truly disconnect the client's connection so that it can connect again?
Server:
import socket, threading, time, json
ONLINE_USERS = []
SESSION = None
class User():
def __init__(user, connection, address):
print('for', address, '{Connection established}')
user.connection = connection
user.address = address
user.character = None
threading.Thread(target=user.process, args=(), daemon=True).start()
def process(user):
time.sleep(1)
user.send("&pLogin\n^^^^^\n")
username = user.send("&iUser>")
password = user.send("&iPass>")
print(user.ping())
print(user.logout())
def send(user, *x):
user.connection.sendall(str.encode(str(x)))
data = user.connection.recv(1024)
return data if data!=b'\x01' else True
def recv(user, x):
user.connection.recv(x)
def ping(user):
start = time.time()
user.connection.sendall(b'\x02')
end = float(user.connection.recv(1024))
return round((end - start) * 1000)
def logout(user):
user.connection.sendall(b'\x04')
return user.connection.recv(4)
class Session():
def __init__(session, host='', port=12345):
session.host = host
session.port = port
session.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
session.socket.bind((host, port))
session.socket.listen(10)
def accept():
conn = User(*session.socket.accept())
session.thread_accept = threading.Thread(target=accept, args=(), daemon=True).start()
def shutdown():
for user in ONLINE_USERS.keys():
ONLINE_USERS[user].connection.sendall(bytes([0xF]))
if __name__ == '__main__':
SESSION = Session()
input('Press heart to continue!\n')
Client:
import socket, sys, threading, time, os
def clear(t=0.5):
time.sleep(t)
os.system('cls')
def tryeval(x, default):
try:
return eval(x)
except:
return default
class Client():
def __init__(client):
try:
server_info = input('IP_ADDRESS:PORT>').split(':')
client.host = server_info[0]
client.port = int(server_info[1])
except:
client.host = 'localhost'
client.port = 12345
client.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.socket.settimeout(10)
try:
client.socket.connect((client.host, client.port))
clear()
client.data_exchange()
finally:
client.shutdown()
def data_exchange(client):
while True:
data = client.socket.recv(1024)
if data:
if data==b'\x02':
client.socket.sendall(str.encode(str(time.time())))
elif data==b'\x04':
client.shutdown()
else:
data = tryeval(data, ())
response = []
for item in data:
try:
prefix, content = item[:2], item[2:]
if prefix=='&p':
print(content, end='')
elif prefix=='&i':
response.append(input(content))
if prefix=='&c':
time.sleep(float(content))
clear()
except:
pass
if len(response)>0:
client.socket.sendall(str.encode(str(tuple(response))))
else:
client.socket.sendall(b'\x01')
time.sleep(0.001)
def shutdown(client):
try:
client.socket.sendall(b'\x04')
except:
pass
print('Shutting down program.')
client.socket.shutdown(socket.SHUT_RDWR)
print('Socket has been shutdown.')
client.socket.close()
print('Socket has been closed.')
print('Exiting program')
time.sleep(1)
sys.exit()
if __name__ == '__main__':
client = Client()
"The server repeatedly calls accept waiting for new incoming connections." No it doesn't. It calls accept once in a thread...which exits. – Mark Tolonen

Categories