I have a code which is written in Twisted and I am having trouble with converting it to Asyncio. From my problem the problem is about protocol in Server class. The code which is written with Twisted is this:
from twisted.internet import reactor, protocol
class Client():
def __init__(self):
self.something = ""
def dataReceived(self, packet):
print(packet)
def makeConnection(self, transport):
self.transport = transport
self.server = self.factory
def connectionLost(self, args):
print("Connection lost.")
class Server(protocol.ServerFactory):
protocol = Client
if __name__ == '__main__':
validPort = []
S = Server()
try:
reactor.listenTCP(44444, S)
validPort.append(44444)
except:
print('Problem about port.')
if not validPort == []:
print('Server is running.')
reactor.run()
And this is the code which I converted to Asyncio and doesnt't work (I am not sure the problem is about protocol in Server Class):
import asyncio, logging, sys
SERVER_ADDRESS = ('localhost', 44444)
logging.basicConfig(
level=logging.DEBUG,
format='%(name)s: %(message)s',
stream=sys.stderr,
)
log = logging.getLogger('main')
event_loop = asyncio.get_event_loop()
class Client():
def __init__(self):
self.something = ""
def data_received(self, packet):
self.log.debug('received {!r}'.format(data))
print(packet)
def connection_made(self, transport):
self.transport = transport
self.server = self.factory
self.log = logging.getLogger(
'EchoServer_{}_{}'.format(*self.address)
)
self.log.debug('connection accepted')
def connection_lost(self, args):
if error:
self.log.error('ERROR: {}'.format(error))
else:
self.log.debug('closing')
super().connection_lost(error)
class Server(asyncio.Protocol):
protocol = Client
if __name__ == '__main__':
S = Server()
factory = event_loop.create_server(S, *SERVER_ADDRESS)
server = event_loop.run_until_complete(factory)
log.debug('starting up on {} port {}'.format(*SERVER_ADDRESS))
try:
event_loop.run_forever()
finally:
log.debug('closing server')
server.close()
event_loop.run_until_complete(server.wait_closed())
log.debug('closing event loop')
event_loop.close()
In asyncio there is no ProtocolFactory abstract interface. Just pass Client or lambda: Client to loop.create_server()
Related
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?
I am trying to build a Python program that will pass a message between a Client and Server. The idea is to pass one message from the Server and have the Client modify it and pass it back to the Server.
Right now I am suck on trying to get the Client's message back to the Server; the message 'Congrats! You have connected' is converted to uppercase,
Server
import socket
class Server:
def __init__(self, host, port):
self.serverSocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
self.host = host
self.port = port
def bind(self):
self.serverSocket.bind((self.host, self.port))
self.serverSocket.listen(5)
def run(self):
while True:
print ('Waiting for a connection')
(clientSocket, addr) = self.serverSocket.accept()
print ('Got a connection from {}'.format(str(addr)))
message = 'Congrats! You have connected'
self.sendMessage(message, clientSocket)
self.recieveMessage()
clientSocket.close()
def sendMessage(self, message, clientSocket):
clientSocket.send(message.encode('ascii'))
def recieveMessage(self):
(clientSocket, addr) = self.serverSocket.accept()
message = self.serverSocket.recv(1024).decode('ascii')
print(message)
def closeSocket(self):
self.serverSocket.close()
if __name__ == '__main__':
myServer = Server('127.0.0.1', 5555)
myServer.bind()
myServer.run()
myServer.recieveMessage()
myServer.closeSocket()
Client
import socket
class Client:
def __init__(self, host, port):
self.serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.host = host
self.port = port
def connect(self):
self.serverSocket.connect((self.host, self.port))
def getMessage(self):
return self.serverSocket.recv(1024).decode('ascii')
def modifyMessage(self):
return message.upper()
def sendMessage(self, upperCaseMessage, server):
(server, addr) = self.serverSocket.accept()
serverSocket.send(upperCaseMessage.encode('ascii'))
def closeConnection(self):
self.serverSocket.close()
if __name__ == '__main__':
myClient = Client('127.0.0.1', 5555)
myClient.connect()
message = myClient.getMessage()
upperCaseMessage = myClient.modifyMessage()
myClient.sendMessage(upperCaseMessage, serverSocket)
myClient.closeConnection()
I'm trying to build a socket and I want to print an object of clients, but for some reason whenever I connect it just returns empty {}
I'm new to Python and would like some insight
import socket
from threading import Thread
from multiprocessing import Process
import time as t
previousTime = t.time()
clients = {}
hostAddr = "127.0.0.1"
hostPort = 80
class sClient(Thread):
def __init__(self, socket, address):
Thread.__init__(self)
self.sock = socket
self.addr = address
self.start()
def run(self):
print("\nClient Connected from {}!".format(self.addr[0]))
self.sock.sendall("Welcome master".encode())
class sHost():
def __init__(self, host, port, clients):
self.sHost = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sHost.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sHost.bind((host, port))
self.sHost.listen()
self.start_listening()
def start_listening(self):
while 1:
clientSocket, clientAddr = self.sHost.accept()
clients[clientSocket.fileno()] = clientSocket
sClient(clientSocket, clientAddr)
def SendMsgToAllClients(msg):
print(clients) # this is empty
for client in clients.values():
try:
client.sendall(msg.encode())
except Exception as e:
print("Client probably disconnected, removing...")
finally:
del clients[client.fileno()]
if __name__ == '__main__':
Process(target=sHost, args=(hostAddr, hostPort, clients)).start()
print("Server is running")
while 1:
if previousTime + 3 <= t.time():
SendMsgToAllClients("Test")
previousTime = t.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
Here is a simple client which connects and sends a text message:
class Client(asyncore.dispatcher):
def __init__(self, host, port):
asyncore.dispatcher.__init__(self)
self.create_socket()
self.connect( (host, port) )
self.buffer = bytes("hello world", 'ascii')
def handle_connect(self):
pass
def handle_close(self):
self.close()
def handle_read(self):
print(self.recv(8192))
def writable(self):
return (len(self.buffer) > 0)
def writable(self):
return True
def handle_write(self):
sent = self.send(self.buffer)
print('Sent:', sent)
self.buffer = self.buffer[sent:]
client = Client('localhost', 8080)
asyncore.loop()
And here is the server which has to receive the message and echo it back:
class Server(asyncore.dispatcher):
def __init__(self, host, port):
asyncore.dispatcher.__init__(self)
self.create_socket()
self.set_reuse_addr()
self.bind((host, port))
self.listen(5)
def handle_read(self):
self.buffer = self.recv(4096)
while True:
partial = self.recv(4096)
print('Partial', partial)
if not partial:
break
self.buffer += partial
def readable(self):
return True
def handle_write(self):
pass
def handle_accepted(self, sock, addr):
print('Incoming connection from %s' % repr(addr))
self.handle_read()
print(self.buffer)
if __name__ == "__main__":
server = Server("localhost", 8080)
asyncore.loop()
The problem is that server isn't reading anything. When I print self.buffer the output is:
b''
What am I doing wrong?
First of all, you need two handlers: One for the server socket (where you expect only accept), and one for the actual communication sockets. In addition, you can only call read once in handle_read; if you call it twice, the second call may block, and that's not allowed in asyncore programming. Don't worry though; if your read did not get everything, you'll immediately be notified again once your read handler returns.
import asyncore
class Handler(asyncore.dispatcher):
def __init__(self, sock):
self.buffer = b''
super().__init__(sock)
def handle_read(self):
self.buffer += self.recv(4096)
print('current buffer: %r' % self.buffer)
class Server(asyncore.dispatcher):
def __init__(self, host, port):
asyncore.dispatcher.__init__(self)
self.create_socket()
self.set_reuse_addr()
self.bind((host, port))
self.listen(5)
def handle_accepted(self, sock, addr):
print('Incoming connection from %s' % repr(addr))
Handler(sock)
if __name__ == "__main__":
server = Server("localhost", 1234)
asyncore.loop()