Python’un asyncio kütüphanesini kullanan basit bir sohbet programı yazdım. İstemciler beklemeden iletişim kurabiliyorlar. Ayrıca, sunucuya bir istemci bağlandığında / bağlantısı kesildiğinde, sunucu konsol penceresine bir bilgi yazdırıyor. Ayrıca, istemcilerin tüm etkinlikleri sunucu tarafından bir günlük dosyasına yazılıyor.
Konsol pencerelerine baktığımda program sorunsuz bir şekilde çalışıyor görünüyor. Bir istemcinin bağlantısı kesildikten bir saniye sonra, bu istemcinin sunucudan ayrıldığı ile ilgili bir bilgi sunucunun konsol penceresine yazılır. Ancak günlük dosyasına baktığımda, sunucunun, bağlı tüm istemcilere boş mesajlar göndermeye çalıştığı görülmektedir. Ancak bu mesajlar istemcilerin pencerelerinde gösterilmiyor (Daha doğrusu bunu engelledim.).
Öyle görünüyor ki, sunucu, bağlantısı kesilmiş istemcileri düzgün şekilde kapatmıyor.
Bu sorunu çözmek için paylaştığım kodlarda nasıl bir değişiklik yapmam gerekiyor? Bu arada günlük dosyasını da paylaşıyorum.
server.py
#!/usr/bin/env python3.7
# -*- coding: utf-8 -*-
import asyncio
import logging
logging.basicConfig(
filename="server.log",
format="- %(levelname)s - %(asctime)s - %(message)s",
level=logging.DEBUG,
datefmt="%d.%m.%Y %H:%M:%S"
)
class Server:
def __init__(self):
self.clients = []
def run(self):
asyncio.run(self.main())
async def client_connected(self, reader, writer):
client = f"{writer.get_extra_info('peername')}"
print(f"{client} is connected.")
logging.info(f"{client} is connected.")
self.clients.append((writer, reader))
while True:
try:
data = await reader.readline()
except (BrokenPipeError, ConnectionResetError):
data = "".encode()
await asyncio.sleep(1)
for i in self.clients:
msg = f"{client}: {data.decode()}"
try:
i[0].write(msg.encode())
logging.debug(msg[:-1])
await i[0].drain()
except (BrokenPipeError, ConnectionResetError):
i[0].close()
self.clients.remove(i)
print(f"{client} is disconnected.")
logging.info(f"{client} is disconnected.")
await asyncio.sleep(2)
break
async def main(self):
server = await asyncio.start_server(
client_connected_cb=self.client_connected,
host="127.0.0.1",
port=12345
)
print(f"Server started on {server.sockets[0].getsockname()}")
logging.info(f"Server started on {server.sockets[0].getsockname()}")
async with server:
await server.wait_closed()
if __name__ == "__main__":
Server().run()
client.py
#!/usr/bin/env python3.7
# -*- coding: utf-8 -*-
import sys
import asyncio
import threading
class Client:
def __init__(self):
self.nick = input("/nick ")
while not self.nick:
self.nick = input("/nick ")
def run(self):
asyncio.run(self.main())
async def read(self, reader, writer):
data = await reader.readline()
socket = writer.get_extra_info('socket').getsockname()
if str(socket) not in data.decode() or \
self.nick not in data.decode():
if data.decode().count("('") >= 1:
data = data.decode().split(": ")[-2:]
print(": ".join(data)[:-1])
async def write(self, writer):
t = threading.Thread(
target=lambda: writer.write(
f"{self.nick}: {sys.stdin.readline()}".encode()
)
)
t.daemon = True
t.start()
t.join(0.1)
await writer.drain()
async def main(self):
reader, writer = await asyncio.open_connection("127.0.0.1", 12345)
print(f"Connected to {writer.get_extra_info('peername')}")
while reader and writer:
await asyncio.gather(
self.read(reader, writer),
self.write(writer)
)
if __name__ == "__main__":
Client().run()
server.log
- DEBUG - 30.09.2019 16:29:36 - Using selector: EpollSelector
- INFO - 30.09.2019 16:29:36 - Server started on ('127.0.0.1', 12345)
- INFO - 30.09.2019 16:29:45 - ('127.0.0.1', 46328) is connected.
- INFO - 30.09.2019 16:29:51 - ('127.0.0.1', 46330) is connected.
- INFO - 30.09.2019 16:30:01 - ('127.0.0.1', 46332) is connected.
- DEBUG - 30.09.2019 16:30:30 - ('127.0.0.1', 46328): Client1: selam
- DEBUG - 30.09.2019 16:30:30 - ('127.0.0.1', 46328): Client1: selam
- DEBUG - 30.09.2019 16:30:30 - ('127.0.0.1', 46328): Client1: selam
- DEBUG - 30.09.2019 16:30:34 - ('127.0.0.1', 46328): Client1: naber?
- DEBUG - 30.09.2019 16:30:34 - ('127.0.0.1', 46328): Client1: naber?
- DEBUG - 30.09.2019 16:30:34 - ('127.0.0.1', 46328): Client1: naber?
- DEBUG - 30.09.2019 16:30:37 - ('127.0.0.1', 46328): Client1: iyi misiniz?
- DEBUG - 30.09.2019 16:30:37 - ('127.0.0.1', 46328): Client1: iyi misiniz?
- DEBUG - 30.09.2019 16:30:37 - ('127.0.0.1', 46328): Client1: iyi misiniz?
- DEBUG - 30.09.2019 16:31:57 - ('127.0.0.1', 46328):
- DEBUG - 30.09.2019 16:31:57 - ('127.0.0.1', 46328):
- DEBUG - 30.09.2019 16:31:57 - ('127.0.0.1', 46328):
- DEBUG - 30.09.2019 16:31:57 - ('127.0.0.1', 46328):
- INFO - 30.09.2019 16:31:57 - ('127.0.0.1', 46328) is disconnected.
- DEBUG - 30.09.2019 16:31:58 - ('127.0.0.1', 46332):
- DEBUG - 30.09.2019 16:31:58 - ('127.0.0.1', 46332):
- DEBUG - 30.09.2019 16:31:58 - ('127.0.0.1', 46332):
- DEBUG - 30.09.2019 16:31:58 - ('127.0.0.1', 46332):
- INFO - 30.09.2019 16:31:58 - ('127.0.0.1', 46332) is disconnected.
- DEBUG - 30.09.2019 16:31:58 - ('127.0.0.1', 46330):
- DEBUG - 30.09.2019 16:31:58 - ('127.0.0.1', 46330):
- INFO - 30.09.2019 16:31:58 - ('127.0.0.1', 46330) is disconnected.
Ekran Görüntüleri: