İstemci sunucudan ayrıldıktan sonra sunucunun ayrılan istemciyle ilgili işlem yapmaya devam etmesini nasıl engellerim?

Bir de, artık ilk kopan istemci hariç diğer istemcilerin sunucudan koptuğunun bilgisi ekrana da log dosyasına da yazdırılmıyor.

O kısım hakkında bilgim yok. Biraz daha bilgi edindikten sonra bir cevap yazabilirim. Şimdilik bu kadar yorum yapabiliyorum malesef…

1 Beğeni

Vakit ayırdığınız için teşekkürler. :slight_smile: Biraz daha uğraşayım izninizle.

1 Beğeni

Rica ederim ne demek, kolay gelsin :slight_smile:

1 Beğeni

Sorun çözüldü görünüyor.

#!/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()
            msg = f"{client}: {data.decode()}"
            if msg.encode() == f"{client}: ".encode():
                writer.close()
                print(f"{client} is disconnected.")
                logging.info(f"{client} is disconnected.")
                await writer.wait_closed()
                self.clients.remove((writer, reader))
                break
            else:
                for i in self.clients:
                    i[0].write(msg.encode())
                    logging.debug(msg[:-1])
                    await i[0].drain()

    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()

Bu da, log dosyasının içeriği:

- DEBUG - 30.09.2019 22:22:21 - Using selector: EpollSelector
- INFO - 30.09.2019 22:22:21 - Server started on ('127.0.0.1', 12345)
- INFO - 30.09.2019 22:22:27 - ('127.0.0.1', 48864) is connected.
- INFO - 30.09.2019 22:22:31 - ('127.0.0.1', 48866) is connected.
- DEBUG - 30.09.2019 22:22:32 - ('127.0.0.1', 48866): veli: selam
- DEBUG - 30.09.2019 22:22:32 - ('127.0.0.1', 48866): veli: selam
- DEBUG - 30.09.2019 22:22:35 - ('127.0.0.1', 48866): veli: naber?
- DEBUG - 30.09.2019 22:22:35 - ('127.0.0.1', 48866): veli: naber?
- DEBUG - 30.09.2019 22:22:37 - ('127.0.0.1', 48866): veli: iyi misin=
- DEBUG - 30.09.2019 22:22:37 - ('127.0.0.1', 48866): veli: iyi misin=
- DEBUG - 30.09.2019 22:22:41 - ('127.0.0.1', 48864): ali: eyvallah
- DEBUG - 30.09.2019 22:22:41 - ('127.0.0.1', 48864): ali: eyvallah
- DEBUG - 30.09.2019 22:22:42 - ('127.0.0.1', 48864): ali: kardeş
- DEBUG - 30.09.2019 22:22:42 - ('127.0.0.1', 48864): ali: kardeş
- INFO - 30.09.2019 22:22:43 - ('127.0.0.1', 48864) is disconnected.
- INFO - 30.09.2019 22:22:47 - ('127.0.0.1', 48868) is connected.
- DEBUG - 30.09.2019 22:22:49 - ('127.0.0.1', 48868): eheh: selam
- DEBUG - 30.09.2019 22:22:49 - ('127.0.0.1', 48868): eheh: selam
- DEBUG - 30.09.2019 22:22:50 - ('127.0.0.1', 48868): eheh: naber?
- DEBUG - 30.09.2019 22:22:50 - ('127.0.0.1', 48868): eheh: naber?
- INFO - 30.09.2019 22:22:50 - ('127.0.0.1', 48868) is disconnected.

Aşağıdaki ifadeye göre kodları yeniden düzenledim:

            try:
                data = await reader.readline()
            except (BrokenPipeError, ConnectionResetError):
                data = "".encode()

Bu iki duruma göre, ya istemciden okunan veri diğer istemcilere gönderilmeye çalışılacak ya da boş bir data verisi kullanıcıya gönderilmeye çalışılacak.

O halde şöyle bir sorgu kullanabiliriz diye düşündüm:

            msg = f"{client}: {data.decode()}"
            if msg.encode() == f"{client}: ".encode():

Bu koşul altında hata veren writerself.clients içinde aramak yerine, doğrudan writer'ı kapatmaya çalıştım. Daha sonra writer kapatılana kadar beklemeye alınır. Kapatıldıktan sonra da self.clients listesinden kopmuş istemcinin writer ve reader özellikleri düşürülür. Ve while döngüsü sonlandırılır.

else koşulunda ise self.clients listesindeki her bir istemciye mesaj gönderilir.

1 Beğeni

Evet boş mesaj sorunu çözülmüş görünüyor. Ancak bu sefer de şu hatayı veriyor

- ERROR - 30.09.2019 22:50:28 - Task exception was never retrieved

Client bağlantısını yapan cmd ekranını kapatınca böyle oluyor. Diğer türlü sonlandıramıyorum.

O hatayı daha önce birçok kez aldım. Bu arada logun tamamına bakabilir miyim izninizle? Son çalıştırdığımda şöyle bir log aldım:

- DEBUG - 30.09.2019 22:54:55 - Using selector: EpollSelector
- INFO - 30.09.2019 22:54:55 - Server started on ('127.0.0.1', 12345)
- INFO - 30.09.2019 22:54:58 - ('127.0.0.1', 48996) is connected.
- INFO - 30.09.2019 22:55:03 - ('127.0.0.1', 48998) is connected.
- DEBUG - 30.09.2019 22:55:05 - ('127.0.0.1', 48998): veli: selam
- DEBUG - 30.09.2019 22:55:05 - ('127.0.0.1', 48998): veli: selam
- DEBUG - 30.09.2019 22:55:06 - ('127.0.0.1', 48998): veli: naber*
- DEBUG - 30.09.2019 22:55:06 - ('127.0.0.1', 48998): veli: naber*
- DEBUG - 30.09.2019 22:55:07 - ('127.0.0.1', 48998): veli: ahahaha
- DEBUG - 30.09.2019 22:55:07 - ('127.0.0.1', 48998): veli: ahahaha
- INFO - 30.09.2019 22:55:12 - ('127.0.0.1', 49000) is connected.
- DEBUG - 30.09.2019 22:55:13 - ('127.0.0.1', 49000): ahaha: ahaha
- DEBUG - 30.09.2019 22:55:13 - ('127.0.0.1', 49000): ahaha: ahaha
- DEBUG - 30.09.2019 22:55:13 - ('127.0.0.1', 49000): ahaha: ahaha
- DEBUG - 30.09.2019 22:55:13 - ('127.0.0.1', 49000): ahaha: ahaha
- DEBUG - 30.09.2019 22:55:13 - ('127.0.0.1', 49000): ahaha: ahaha
- DEBUG - 30.09.2019 22:55:13 - ('127.0.0.1', 49000): ahaha: ahaha
- DEBUG - 30.09.2019 22:55:14 - ('127.0.0.1', 49000): ahaha: ahaha
- DEBUG - 30.09.2019 22:55:14 - ('127.0.0.1', 49000): ahaha: ahaha
- DEBUG - 30.09.2019 22:55:14 - ('127.0.0.1', 49000): ahaha: ahaha
- DEBUG - 30.09.2019 22:55:17 - ('127.0.0.1', 49000): ahaha: naber?
- DEBUG - 30.09.2019 22:55:17 - ('127.0.0.1', 49000): ahaha: naber?
- DEBUG - 30.09.2019 22:55:17 - ('127.0.0.1', 49000): ahaha: naber?
- INFO - 30.09.2019 22:55:19 - ('127.0.0.1', 49000) is disconnected.
- INFO - 30.09.2019 22:55:23 - ('127.0.0.1', 49002) is connected.
- DEBUG - 30.09.2019 22:55:25 - ('127.0.0.1', 49002): ehehe: hahahaha
- DEBUG - 30.09.2019 22:55:25 - ('127.0.0.1', 49002): ehehe: hahahaha
- DEBUG - 30.09.2019 22:55:25 - ('127.0.0.1', 49002): ehehe: hahahaha
- INFO - 30.09.2019 22:55:25 - ('127.0.0.1', 49002) is disconnected.
- DEBUG - 30.09.2019 22:55:28 - ('127.0.0.1', 48998): veli: wfkwkf
- DEBUG - 30.09.2019 22:55:28 - ('127.0.0.1', 48998): veli: wfkwkf
- INFO - 30.09.2019 22:55:29 - ('127.0.0.1', 48998) is disconnected.
- DEBUG - 30.09.2019 22:55:33 - ('127.0.0.1', 48996): ali: ajajaa
- INFO - 30.09.2019 22:55:34 - ('127.0.0.1', 48996) is disconnected.
1 Beğeni

Tabi ki

DEBUG - 30.09.2019 22:54:58 - Using selector: SelectSelector
- INFO - 30.09.2019 22:54:58 - Server started on ('127.0.0.1', 12345)
- INFO - 30.09.2019 22:55:16 - ('127.0.0.1', 49857) is connected.
- INFO - 30.09.2019 22:55:24 - ('127.0.0.1', 49860) is connected.
- DEBUG - 30.09.2019 22:55:32 - ('127.0.0.1', 49857): user1: merhaba
- DEBUG - 30.09.2019 22:55:32 - ('127.0.0.1', 49857): user1: merhaba
- DEBUG - 30.09.2019 22:55:36 - ('127.0.0.1', 49860): user2: merhaba kardeş
- DEBUG - 30.09.2019 22:55:36 - ('127.0.0.1', 49860): user2: merhaba kardeş
- DEBUG - 30.09.2019 22:55:47 - ('127.0.0.1', 49857): user1: by
- DEBUG - 30.09.2019 22:55:47 - ('127.0.0.1', 49857): user1: by
- INFO - 30.09.2019 22:55:55 - ('127.0.0.1', 49857) is disconnected.
- ERROR - 30.09.2019 22:55:55 - Task exception was never retrieved
future: <Task finished coro=<Server.client_connected() done, defined at a_server.py:23> exception=ConnectionResetError(10054, 'Varolan bir bağlantı uzaktaki bir ana bilgisayar tarafından zorla kapatıldı', None, 10054, None)>
Traceback (most recent call last):
  File "a_server.py", line 38, in client_connected
    await writer.wait_closed()
  File "C:\Python37\lib\asyncio\streams.py", line 323, in wait_closed
    await self._protocol._closed
  File "a_server.py", line 30, in client_connected
    data = await reader.readline()
  File "C:\Python37\lib\asyncio\streams.py", line 496, in readline
    line = await self.readuntil(sep)
  File "C:\Python37\lib\asyncio\streams.py", line 588, in readuntil
    await self._wait_for_data('readuntil')
  File "C:\Python37\lib\asyncio\streams.py", line 473, in _wait_for_data
    await self._waiter
  File "C:\Python37\lib\asyncio\selector_events.py", line 804, in _read_ready__data_received
    data = self._sock.recv(self.max_size)
ConnectionResetError: [WinError 10054] Varolan bir bağlantı uzaktaki bir ana bilgisayar tarafından zorla kapatıldı
- DEBUG - 30.09.2019 22:56:00 - ('127.0.0.1', 49860): user2: by
- ERROR - 30.09.2019 22:56:00 - Task exception was never retrieved
future: <Task finished coro=<Server.client_connected() done, defined at a_server.py:23> exception=ConnectionResetError(10054, 'Varolan bir bağlantı uzaktaki bir ana bilgisayar tarafından zorla kapatıldı', None, 10054, None)>
Traceback (most recent call last):
  File "a_server.py", line 45, in client_connected
    await i[0].drain()
  File "C:\Python37\lib\asyncio\streams.py", line 339, in drain
    raise exc
  File "a_server.py", line 38, in client_connected
    await writer.wait_closed()
  File "C:\Python37\lib\asyncio\streams.py", line 323, in wait_closed
    await self._protocol._closed
  File "a_server.py", line 30, in client_connected
    data = await reader.readline()
  File "C:\Python37\lib\asyncio\streams.py", line 496, in readline
    line = await self.readuntil(sep)
  File "C:\Python37\lib\asyncio\streams.py", line 588, in readuntil
    await self._wait_for_data('readuntil')
  File "C:\Python37\lib\asyncio\streams.py", line 473, in _wait_for_data
    await self._waiter
  File "C:\Python37\lib\asyncio\selector_events.py", line 804, in _read_ready__data_received
    data = self._sock.recv(self.max_size)
ConnectionResetError: [WinError 10054] Varolan bir bağlantı uzaktaki bir ana bilgisayar tarafından zorla kapatıldı

Kullanıcı 1 bağlandı, kullanıcı 2 bağlandı. Daha sonra kullanıcı1 mesaj gönderdikten sonra cmd ekranını kapattım. Ve kullanıcı2 penceresini de kapattım.

Server üzerinde kullanıcı 1 için sonlandı yazıyor ama, kullanıcı 2 için yazmıyor

Şaşkın şaşkın bakıyorum paylaştığınız ekran çıktısına. :slight_smile: Acaba bu hatayı neye bağlı olarak veriyor?

1 Beğeni

İnanın ben de bilmiyorum. Ama çözmek için uğraşıyorum.

1 Beğeni

Acaba Windows’tan mı kaynaklanıyor anlamadım ki. Mesela aşağıdaki çıktı son aldığım çıktı ve hiç hata gözükmüyor.

- DEBUG - 30.09.2019 23:06:36 - Using selector: EpollSelector
- INFO - 30.09.2019 23:06:36 - Server started on ('127.0.0.1', 12345)
- INFO - 30.09.2019 23:06:39 - ('127.0.0.1', 49016) is connected.
- INFO - 30.09.2019 23:06:40 - ('127.0.0.1', 49016) is disconnected.
- INFO - 30.09.2019 23:06:45 - ('127.0.0.1', 49018) is connected.
- INFO - 30.09.2019 23:06:46 - ('127.0.0.1', 49018) is disconnected.
- INFO - 30.09.2019 23:06:49 - ('127.0.0.1', 49020) is connected.
- INFO - 30.09.2019 23:06:50 - ('127.0.0.1', 49020) is disconnected.
- INFO - 30.09.2019 23:06:52 - ('127.0.0.1', 49022) is connected.
- INFO - 30.09.2019 23:06:53 - ('127.0.0.1', 49022) is disconnected.
- INFO - 30.09.2019 23:07:11 - ('127.0.0.1', 49024) is connected.
- INFO - 30.09.2019 23:07:11 - ('127.0.0.1', 49024) is disconnected.
- INFO - 30.09.2019 23:07:14 - ('127.0.0.1', 49026) is connected.
- INFO - 30.09.2019 23:07:15 - ('127.0.0.1', 49026) is disconnected.
- INFO - 30.09.2019 23:07:17 - ('127.0.0.1', 49028) is connected.
- INFO - 30.09.2019 23:07:22 - ('127.0.0.1', 49030) is connected.
- INFO - 30.09.2019 23:07:23 - ('127.0.0.1', 49030) is disconnected.
- INFO - 30.09.2019 23:07:26 - ('127.0.0.1', 49032) is connected.
- INFO - 30.09.2019 23:07:26 - ('127.0.0.1', 49032) is disconnected.
- INFO - 30.09.2019 23:07:28 - ('127.0.0.1', 49034) is connected.
- INFO - 30.09.2019 23:07:29 - ('127.0.0.1', 49034) is disconnected.
- INFO - 30.09.2019 23:07:32 - ('127.0.0.1', 49036) is connected.
- INFO - 30.09.2019 23:07:32 - ('127.0.0.1', 49036) is disconnected.
- INFO - 30.09.2019 23:07:35 - ('127.0.0.1', 49038) is connected.
- DEBUG - 30.09.2019 23:07:36 - ('127.0.0.1', 49038): b: aaa
- DEBUG - 30.09.2019 23:07:36 - ('127.0.0.1', 49038): b: aaa
- DEBUG - 30.09.2019 23:07:37 - ('127.0.0.1', 49038): b: ehehehe
- DEBUG - 30.09.2019 23:07:37 - ('127.0.0.1', 49038): b: ehehehe
- INFO - 30.09.2019 23:07:38 - ('127.0.0.1', 49038) is disconnected.
- INFO - 30.09.2019 23:07:44 - ('127.0.0.1', 49040) is connected.
- DEBUG - 30.09.2019 23:07:45 - ('127.0.0.1', 49040): akaka: wkfwkf
- DEBUG - 30.09.2019 23:07:45 - ('127.0.0.1', 49040): akaka: wkfwkf
- DEBUG - 30.09.2019 23:07:45 - ('127.0.0.1', 49040): akaka: wfwf
- DEBUG - 30.09.2019 23:07:45 - ('127.0.0.1', 49040): akaka: wfwf
- INFO - 30.09.2019 23:07:46 - ('127.0.0.1', 49040) is disconnected.
- INFO - 30.09.2019 23:07:47 - ('127.0.0.1', 49028) is disconnected.

Siz bağlantıyı nasıl sonlandırıyorsunuz acaba merak ettim. Ben CTRL-C ile sonlandıramıyorum. Onun yerine pencereyi kapatmak durumunda kalıyorum.

Evet, ctrl-c ile sonlandırıyorum.

Siz öyle deyince, X işaretinden sonlandırayım dedim ancak değişen bir şey olmadı.

Anladım. Windows cmd üzerinden CTRL-C ile kapatamadım henüz… Ancak kapanmadığı halde, mesaj gönderilemiyor. Sadece imlec yanıp sönüyor, mesaj girişi yapılamıyor.

Bunlar benim bilgisayarımdaki denemelerim. Başkaları da denerse, belki daha farklı sonuçlar elde edebiliriz

Client penceresinin tam kapanmaması thread’den kaynaklanıyor olabilir belki.

1 Beğeni

Kodlarda şöyle bir değişiklik yapılsa nasıl olur?
Mesela son satırda Client sınıfından bir örnek oluşturup bunun run metodunu çağırmak yerine, bir thread oluşturulur ve run metodu thread’e argüman olarak aktarılır. Bilmiyorum daha denemedim. Şunun gibi:

if __name__ == "__main__":
    t_main = threading.Thread(target=lambda: Client().run())
    t_main.run()

Bilmiyorum ama, bana nedense pek bir şey değişmeyecek gibi geliyor.

Windows’ta programı ctrl-c ile kapatabilmek içindi bu kodlar bu arada. Daha önce threadler yüzünden böyle bir durumla karşılaşmıştım.

Dediğiniz şekilde değişiklik yaptım. Ancak aynı durum devam ediyor. CTRL-C ile kapatılmıyor.