Python ile Socket Programlama 4
Merhabalar, One to One Chat(1’e 1 mesajlaşma) uygulamamızı AsyncIO kullanarak yeniden yapacağımızı söylemiştik gelin birlikte yapalim.
Yazımızda bir önceki AsyncIO socket örneğinden alıntılara yer vereceğim için AsyncIO ile Basit Socket Örneği yazımı okumanızı tavsiye ederim.
Python Socket 1’e 1 Mesajlaşma Örneği(AsyncIO ile)
Bir önceki yazımızda da bahsettiğimiz gibi
Server.py dosyamızı yazarken AsyncIO kullanacağız.
Not: Bu örnekte string ve seperatorleri kullanarak haberleşmeyi sağladık. Daha iyi bir kullanım ve kontrol için json kullanabilirsiniz.
# server.py import socket import asyncio HEADER = 64 IP = socket.gethostbyname(socket.gethostname()) PORT = 9999 ADDR = (IP, PORT) FORMAT = 'utf-8' DISCONNECT_MESSAGE = "DISCONNECT_SERVER_CODE" USERNAME_MESSAGE = "EXAMPLE_APP_USERNAME_FIELD" SEP = "///**//" server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind(ADDR) users = [] async def send_message(to_username, msg): for user in users: if user['username'] == to_username: loop = asyncio.get_event_loop() connection = user["connection"] msg = msg.encode(FORMAT) msg_lenth = str(len(msg)).encode(FORMAT) header = msg_lenth + b' ' * (HEADER - len(msg_lenth)) await loop.sock_sendall(connection, header) await loop.sock_sendall(connection, msg) break # we can add if check for if there is no user named like client want def delete_connection(username): for (idx, user) in enumerate(users): if user['username'] == username: del users[idx] async def handle_client(conn, addr): print("[New Connection] {addr} connected...") loop = asyncio.get_event_loop() connected = True while connected: max_lenth = await loop.sock_recv(conn, HEADER) max_lenth = max_lenth.decode(FORMAT) if max_lenth: max_lenth = int(max_lenth) msg = await loop.sock_recv(conn, max_lenth) msg = msg.decode(FORMAT) messages = msg.split(SEP) username = messages[0] print(f"{users}") if USERNAME_MESSAGE in msg: # first connect write to users list data = { "username": username, "connection": conn } users.append(data) continue elif DISCONNECT_MESSAGE in msg: # connection closed delete from user list print("[Disconnect] Disconnecting from server") delete_connection(username) connected = False elif len(messages) > 2: # one to one messagging print(f"[{addr}] message will send -> {msg}") to_username = messages[1] await send_message(to_username, msg) print(f"{len(asyncio.all_tasks())}") conn.close() async def start(): server.listen() print(f"[Listening] Server is Listening now on {IP}") loop = asyncio.get_event_loop() while True: conn, addr = await loop.sock_accept(server) loop.create_task(handle_client(conn, addr)) if __name__ == "__main__": print("[Starting] Socket Server is starting... Stand By") asyncio.run(start())
Kodu incelediğiniz de basit AsyncIO örneği ile benzerlikleri bulunduğunu göreceksiniz.
loop = asyncio.get_event_loop() while True: conn, addr = await loop.sock_accept(server) loop.create_task(handle_client(conn, addr))
Yukarıda ki kod parçacığını tekrar hatırlayacak olursak:
if max_lenth: max_lenth = int(max_lenth) msg = await loop.sock_recv(conn, max_lenth) msg = msg.decode(FORMAT) messages = msg.split(SEP) username = messages[0] print(f"{users}") if USERNAME_MESSAGE in msg: # first connect write to users list data = { "username": username, "connection": conn } users.append(data) continue elif DISCONNECT_MESSAGE in msg: # connection closed delete from user list print("[Disconnect] Disconnecting from server") delete_connection(username) connected = False elif len(messages) > 2: # one to one messagging print(f"[{addr}] message will send -> {msg}") to_username = messages[1] await send_message(to_username, msg)
Kodumuzu incelediğimiz de mesajı aldıktan sonra işlemler yapıldığını görüyoruz. Gelin bu işlemleri inceleyelim.
if USERNAME_MESSAGE in msg: # first connect write to users list data = { "username": username, "connection": conn } users.append(data) continue
Mesajı aldıktan sonra ilk kez mi bağlantı oluşturduğunu anlamak için mesaj içerisine gömülmüş belirli bir yapıyı aratıyoruz. Eğer ilk kez bağlandıysa bağlantı bilgisini users adlı listeye ekliyoruz.
elif DISCONNECT_MESSAGE in msg: # connection closed delete from user list print("[Disconnect] Disconnecting from server") delete_connection(username) connected = False
İkinci olarak ise bağlantıyı koparmak isteyip istemediğini kontrol ediyoruz. Eğer belirlenmiş olan özel yapı mesaj içerisinde var ise bağlantı bilgilerini listeden silmesi için fonksiyona gönderiyoruz. Bilgileri listeden silindiğinde kullanıcılar bilgileri silinen kullanıcıya mesaj atamayacaklar.
elif len(messages) > 2: # one to one messagging print(f"[{addr}] message will send -> {msg}") to_username = messages[1] await send_message(to_username, msg)
Son olarak belli bir yapıya göre parse ettiğimiz mesajı mesaj, gönderen ve gönderdiği kişi gibi bilgiler var mı kontrol ediyoruz. Sonrasında mesajı “send_message” fonksiyonuna gönderiyoruz.
Client kodumuzu inceleyecek olursak Python Socket 1’e 1 Mesajlaşma Örneği(Thread ile) yazımda kullandığım client kodunun aynısı olduğunu göreceksiniz. Siz isterseniz bu kodu AsyncIO ile yazabilirsiniz.
import socket from threading import Thread HEADER = 64 PORT = 9999 FORMAT = 'utf-8' DISCONNECT_MESSAGE = "DISCONNECT_SERVER_CODE" USERNAME_MESSAGE = "EXAMPLE_APP_USERNAME_FIELD" SEP = "///**//" IP = socket.gethostbyname(socket.gethostname()) ADDR = (IP, PORT) client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect(ADDR) def send(msg): message = msg.encode(FORMAT) msg_lenth = str(len(message)).encode(FORMAT) header = msg_lenth + b' ' * (HEADER - len(msg_lenth)) client.send(header) client.send(message) def main(username, to_username): # send(f"{username}{SEP}{DISCONNECT_MESSAGE}") while True: message = input("") if message == "disconnect": send(f"{username}{SEP}{DISCONNECT_MESSAGE}") send(f"{username}{SEP}{to_username}{SEP}{message}") def listen(username): # should check for main thread if it closed we need to terminate listen thread. connected = True while connected: max_lenth = client.recv(HEADER).decode(FORMAT) if max_lenth: max_lenth = int(max_lenth) msg = client.recv(max_lenth).decode(FORMAT) messages = msg.split(SEP) if len(messages) > 2: if messages[1] == username: print(f"\n {messages[0]} --> {messages[2]} \n") else: print("security issue check server.py ") if __name__ == "__main__": username = input("Please write your user name: ") if username: send(f"{username}{SEP}{USERNAME_MESSAGE}") to_username = input(f"who you will send message: ") print("you can write your message and press enter") main_thread = Thread(target=main, args=(username, to_username,)) listen_thread = Thread(target=listen, args=(username,)) main_thread.daemon = True main_thread.start() listen_thread.start()
Python ile Socket Programlama Serimizin sonuna geldik.
Bu serimizde socket hakkında bilgiler verip, Thread ve AsyncIO ile socket yazılımları yazdık.
Tüm yazılara ulaşmak için -> Python Socket Programlama