Socket Modülüyle Yapılmış Chat Uygulaması Örneği

Aşağıda paylaşmış olduğum uygulamaya belki ilerleyen zamanlarda yeni özellikler eklenebilir. Veya yine socket modülüyle yapılmış başka programlar paylaşılabillir. Bazı özel şartlarda oluşan tespit edebildiğim program hatalarını giderdim. Belki öngöremediğim bazı hatalar kalmış olabilir. Şayet bu hataları tespit edebilirsem, burada paylaşırım. Eğer programı dener ve hata tespit ederseniz, siz de hataları düzeltebilirsiniz veya hata bildiriminde bulunabilirsiniz.

1. Dosya gönderme özelliği olan bir gui chat uygulaması.
Kaynak kodları: https://github.com/dildeolupbiten/A-gui-chat-program

13 Beğeni

Gui versiyonunda port yerine host yazılmış sanırım. Connect butonuna basınca açılan kısımda.

Evet öyle yazılmış, onu değiştirmem lazım.

Edit: Port yazılması gerektiği halde Host yazılmış yerlerde gerekli değişiklik yapıldı.

Bir soru sormak istiyorum:
Socket programlamada neden client ve server adında ayrı dosyalar oluşturulur? Amacı nedir?

Server (sunucu) ve client (istemci) arasında iletişim kurmak için. Sunucu bir makinede, istemci başka bir makinede bulunur.

1 Beğeni

Sunucu veriyi alıyor, istemci yolluyor öyle mi?

Sunucu istemcinin baglandigi makinedir. Sunucu ile istemci karsilikli mesaj alisverisinde bulunabilirler. Veya sunucu kendisine baglanan iki veya daha cok istemci arasindaki iletisimi duzenler. Yani istemciler birbirleriyle sunucu uzerinden iletisim kurarlar.

2 Beğeni

Socket programlama için sadece python değil bence az da olsa network bilgisi lazım. Network ile ilgili kaynaklar okursanız daha iyi anlayacaksınız socket programlamayı. :slight_smile:

2 Beğeni

Hocam depo bağlantısı kırık.

@dildeolupbiten kodların güncel hali halen var mı hocam?

Buyrun. O zamanlar kodları biraz karışık yazmışım, mazur görün. Bir de görünüşe göre bazı gereksiz veya şuan kullanmak istemeyeceğim kodlar da var.

server.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import re
import os
import time
import socket
import threading
from datetime import datetime
try:
    import Tkinter as tk
except ImportError:
    import tkinter as tk
try:
    import ttk
except ImportError:
    import tkinter.ttk as ttk
try:
    import Tkinter.tkFileDialog as filedialog
except ImportError:
    import tkinter.filedialog as filedialog

root = tk.Tk()
root.title("Server")
right_frame = tk.Frame(master=root)
right_frame.pack(side="right", fill="y", expand=True)
right_frame_label = tk.Label(master=right_frame, text="Client Connections", width=78, bd=1, relief="sunken")
right_frame_label.pack(side="top", fill="x")
text = tk.Text(master=root, state="disabled")
text.pack(expand=True, fill="both")
count = 1
tag_name = ""


def tag(now, name, nickname="", color="black"):
    len1 = len(now) + 2
    len2 = len(nickname) + 1
    text.tag_add(name + "0", "{}.0".format(count), "{}.1".format(count))
    text.tag_configure(name + "0", foreground="green")
    text.tag_add(name + "1", "{}.1".format(count), "{}.{}".format(count, len1))
    text.tag_configure(name + "1", foreground="purple")
    text.tag_add(name + "2", "{}.{}".format(count, len1), "{}.{}".format(count, len1 + 2))
    text.tag_configure(name + "2", foreground="green")
    text.tag_add(name + "3", "{}.{}".format(count, len1 + 2), "{}.{}".format(count, len1 + len2 + 2))
    text.tag_configure(name + "3", foreground=color)


def tag_controller(message, nickname="", color="black"):
    global count, tag_name
    text.configure(state="normal")
    text.insert("insert", "| {} | {}\n".format(str(datetime.now())[:-7], message))
    text.configure(state="disabled")
    tag(now=str(datetime.now())[:-7], name=tag_name, nickname=nickname, color=color)
    count += 1
    tag_name += str(count)


button_frame = tk.Frame(master=root)
button_frame.pack()


def buttons(*args, master):
    for i in args:
        b = tk.Button(master=master, text=i)
        b.pack(side="left")
        yield b


b1, b2, b3, b4 = buttons("Connect", "Clear", "File Transfer", "Exit", master=button_frame)


def do_nothing():
    pass


class Server:
    clients1 = []
    clients2 = []
    client_names = []
    client_frames = []

    def __init__(self):
        self.s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    def __connect__(self, port):
        try:
            self.s1.bind(("localhost", port))
            self.s1.listen(10)
            self.s2.bind(("", port + 1))
            self.s2.listen(10)
            tag_controller(message="Connected.")

            def warning():
                tag_controller(message="You are already connected.")

            b1.configure(command=warning)
            self.thread_control()
        except PermissionError:
            tag_controller(message="Permission denied.")
        except OverflowError:
            tag_controller(message="Port must be 0-65535.")
        except OSError:
            tag_controller(message="Address already in use.")

    def __accept__(self):
        conn1, addr1 = self.s1.accept()
        conn2, addr2 = self.s2.accept()
        data = conn1.recv(1024).decode("utf-8")
        self.client_names.append(data)
        self.clients1.append((conn1, data))
        self.clients2.append((conn2, data))
        tag_controller(message="{} connected.".format(data), nickname=data, color="red")
        client_frame = tk.Frame(master=right_frame)
        client_frame.pack()
        self.client_frames.append(client_frame)
        client_label = tk.Label(master=client_frame, text=data, width=20, bd=1, relief="sunken")
        client_label.pack(side="left")
        entry = tk.Entry(master=client_frame, width=50)
        entry.pack(side="left")
        b5, = buttons("Send", master=client_frame)

        def send():

            def __send__():
                respond = ".:!:.Server: {}.:!:.".format(str(entry.get()))
                entry.delete("0", "end")
                try:
                    conn1.sendall(bytes(respond.encode("utf-8")))
                    tag_controller(message="{}".format(respond.replace(".:!:.", "")), nickname="Server", color="blue")
                except (BrokenPipeError, ConnectionResetError, ConnectionAbortedError):
                    pass

            thread_send = threading.Thread(target=__send__)
            thread_send.start()

        b5.configure(command=send)

        def receive_message():
            while True:
                try:
                    data1 = conn1.recv(1024)
                    regex = b"".join(re.findall(b"\.:!:\.[^{}]+: [^{}]+\.:!:\.", data1))
                    if regex:
                        tag_controller(message="{}".format(regex.replace(b".:!:.", b"").decode("utf-8")),
                                       nickname=data, color="red")
                except (ConnectionResetError, OSError):
                    pass

        thread_receive_message = threading.Thread(target=receive_message)
        thread_receive_message.start()

        def receive_file():
            global count
            __filename__ = ""
            __filesize__ = 0
            __received__ = 0
            __now__ = 0
            pframe = tk.Frame(master=root)
            pbar = ttk.Progressbar(master=pframe, orient="horizontal", length=200, mode="determinate")
            pstring = tk.StringVar()
            plabel = tk.Label(master=pframe, textvariable=pstring)
            while True:
                try:
                    data2 = conn2.recv(1024 ** 2)
                    regex = b"".join(re.findall(b"\.:!:\.[^{}]+&[^{}]+\.:!:\.", data2))
                    if regex:
                        filename, filesize = regex.replace(b".:!:.", b"").decode("utf-8").split("&")
                        __filename__ += filename
                        __filesize__ += int(filesize)
                        tag_controller(message="{} wants to send you {}.".format(data, filename), nickname=data,
                                       color="red")
                        tag_controller(message="Size: {} byte.".format(filesize), nickname="Size", color="brown")
                        if pframe is None and pbar is None and plabel is None:
                            pframe = tk.Frame(master=root)
                            pframe.pack()
                            pbar = ttk.Progressbar(master=pframe, orient="horizontal", length=200, mode="determinate")
                            pbar.pack(side="left")
                            plabel = tk.Label(master=pframe, textvariable=pstring)
                            plabel.pack(side="left")
                        else:
                            pframe.pack()
                            pbar.pack(side="left")
                            plabel.pack(side="left")
                        __now__ = time.time()
                        time.sleep(1)
                    else:
                        if __filename__ == "":
                            pass
                        else:
                            with open("new_{}".format(__filename__), "ab") as f:
                                f.write(data2)
                                __received__ += len(data2)
                                if __filesize__ == __received__:
                                    tag_controller(message="{} is received.".format(__filename__),
                                                   nickname=__filename__, color="orange")
                                    __filename__ = ""
                                    __filesize__ = 0
                                    __received__ = 0
                                    pframe.destroy()
                                    pframe = None
                                    pbar = None
                                    plabel = None
                                else:
                                    pbar["value"] = __received__
                                    pbar["maximum"] = __filesize__
                                    pstring.set("{} %,  {} b/s, {} seconds remaining.".format(
                                        int(100 * __received__ / __filesize__),
                                        int(__received__ / (time.time() - __now__)),
                                        int(__filesize__ / (__received__ / (time.time() - __now__))) - int(
                                            time.time() - __now__)))
                except (ConnectionResetError, OSError):
                    if pframe is not None:
                        pframe.destroy()
                        pframe = None
                        pbar = None
                        plabel = None

        thread_receive_file = threading.Thread(target=receive_file)
        thread_receive_file.start()

    def file_transfer(self):
        b3.configure(command=do_nothing)
        __frame__ = tk.Frame(master=root)
        __frame__.pack()

        def client_names(name):

            def __client__names__():

                def __file_transfer__():
                    try:
                        name_index = self.client_names.index(name)
                        file = filedialog.askopenfilename(filetypes=[("All Files", ".*")])
                        try:
                            filename = os.path.basename(file)
                            file = open(file, "rb")
                            data = file.read()

                            def send_file_info():
                                try:
                                    self.clients2[name_index][0].sendall(
                                        bytes(".:!:.{}&{}.:!:.".format(filename, str(len(data))).encode("utf-8")))
                                except (ConnectionResetError, BrokenPipeError, IndexError):
                                    pass

                            thread_send_file_info = threading.Thread(target=send_file_info)
                            thread_send_file_info.start()
                            time.sleep(1)
                            while data:
                                try:
                                    self.clients2[name_index][0].sendall(data)
                                    data = file.read()
                                except (ConnectionResetError, BrokenPipeError, IndexError):
                                    __frame__.destroy()
                            file.close()
                            __frame__.destroy()
                        except (TypeError, FileNotFoundError):
                            __frame__.destroy()
                    except ValueError:
                        __frame__.destroy()

                thread_file_transfer = threading.Thread(target=__file_transfer__)
                thread_file_transfer.start()

            return __client__names__

        for i, j in enumerate(self.client_names):
            b6, = buttons(j, master=__frame__)
            b6.configure(command=client_names(self.client_names[i]))
        b3.configure(command=self.file_transfer)

    def __manage_variables__(self):
        for i, j in enumerate(self.clients1):
            try:
                j[0].send(bytes(".:!:.test.:!:.".encode("utf-8")))
            except (BrokenPipeError, ConnectionResetError, ConnectionAbortedError):
                tag_controller(message="{} is disconnected.".format(j[1]), nickname=j[1], color="red")
                self.client_frames[i].destroy()
                self.client_frames.pop(i)
                self.client_names.pop(i)
                j[0].close()
                self.clients2[i][0].close()
                self.clients2.pop(i)
                self.clients1.pop(i)

    def thread_control(self):
        while True:
            thread_accept = threading.Thread(target=self.__accept__)
            thread_accept.daemon = True
            thread_accept.start()
            thread_accept.join(1)
            thread_manage = threading.Thread(target=self.__manage_variables__)
            thread_manage.daemon = True
            thread_manage.start()
            thread_manage.join(1)


server = Server()


def connect():
    b1.configure(command=do_nothing)
    connect_frame = tk.Frame(master=root)
    connect_frame.pack(side="bottom")
    port_label = tk.Label(master=connect_frame, text="PORT: ")
    port_label.grid(row=0, column=0)
    port_entry = tk.Entry(master=connect_frame, width=10)
    port_entry.grid(row=0, column=1)
    accept_port = tk.Button(master=connect_frame, text="Accept")
    accept_port.grid(row=0, column=2, columnspan=2)

    def accept():
        b1.configure(command=connect)
        try:
            thread_connect = threading.Thread(target=server.__connect__, args=(int(port_entry.get()),))
            thread_connect.start()
        except ValueError:
            tag_controller(message="Port value is invalid.")
        connect_frame.destroy()

    accept_port.configure(command=accept)


def clear():
    global count
    text.configure(state="normal")
    text.delete("1.0", "end")
    text.configure(state="disabled")
    count = 1


def destroy():
    server.s1.close()
    server.s2.close()
    if os.name == "posix":
        import signal
        os.kill(os.getpid(), signal.SIGKILL)
    elif os.name == "nt":
        os.system("TASKKILL /F /PID {}".format(os.getpid()))


b1.configure(command=connect)
b2.configure(command=clear)
b3.configure(command=server.file_transfer)
b4.configure(command=destroy)

if __name__ == "__main__":
    if os.name == "nt":

        def source_path(relative_path):
            import sys
            base_path = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__)))
            return os.path.join(base_path, relative_path)

        root.iconbitmap(source_path("tkicon.ico"))
    main_thread = threading.Thread(target=root.mainloop)
    main_thread.run()

client.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import re
import os
import time
import socket
import requests
import threading
from datetime import datetime
try:
    import Tkinter as tk
except ImportError:
    import tkinter as tk
try:
    import ttk
except ImportError:
    import tkinter.ttk as ttk
try:
    import Tkinter.tkFileDialog as filedialog
except ImportError:
    import tkinter.filedialog as filedialog


root = tk.Tk()
root.title("Client")
text = tk.Text(master=root, state="disabled")
text.pack(expand=True, fill="both")
count = 1
tag_name = ""


def tag(now, name, nickname="", color="black"):
    len1 = len(now) + 2
    len2 = len(nickname) + 1
    text.tag_add(name + "0", "{}.0".format(count), "{}.1".format(count))
    text.tag_configure(name + "0", foreground="green")
    text.tag_add(name + "1", "{}.1".format(count), "{}.{}".format(count, len1))
    text.tag_configure(name + "1", foreground="purple")
    text.tag_add(name + "2", "{}.{}".format(count, len1), "{}.{}".format(count, len1 + 2))
    text.tag_configure(name + "2", foreground="green")
    text.tag_add(name + "3", "{}.{}".format(count, len1 + 2), "{}.{}".format(count, len1 + len2 + 2))
    text.tag_configure(name + "3", foreground=color)


def tag_controller(message, nickname="", color="black"):
    global count, tag_name
    text.configure(state="normal")
    text.insert("insert", "| {} | {}\n".format(str(datetime.now())[:-7], message))
    text.configure(state="disabled")
    tag(now=str(datetime.now())[:-7], name=tag_name, nickname=nickname, color=color)
    count += 1
    tag_name += str(count)


entry = tk.Entry(master=root)
entry.pack(expand=True, fill="x")
frame = tk.Frame(master=root)
frame.pack()


def buttons(*args, master, side):
    for i in args:
        b = tk.Button(master=master, text=i)
        b.pack(side=side)
        yield b


b1, b2, b3, b4, b5, b6 = buttons("Connect", "Create A Nickname", "Send", "Clear", "File Transfer", "Exit",
                                 master=frame, side="left")
__nickname__ = ""


def do_nothing():
    pass


class Client:

    def __init__(self):
        self.s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    def __connect__(self, host, port):
        try:
            self.s1.connect((host, port))
            self.s2.connect((host, port + 1))
            tag_controller(message="Connected.")
            self.s1.sendall(bytes("{}".format(__nickname__).encode("utf-8")))

            def warning():
                tag_controller(message="You are already connected.")

            b1.configure(command=warning)
            thread_receive_message = threading.Thread(target=self.receive_message)
            thread_receive_message.start()
            thread_receive_file = threading.Thread(target=self.receive_file)
            thread_receive_file.start()
        except ConnectionRefusedError:
            tag_controller(message="The server is not online.")
        except socket.gaierror:
            tag_controller(message="Name or service is unknown.")
        except TimeoutError:
            tag_controller(message="Timed out.")
        except OverflowError:
            tag_controller(message="Port must be 0-65535.")

    def receive_message(self):
        while True:
            try:
                data1 = self.s1.recv(1024)
                if ".:!:.test.:!:.".encode("utf-8") in data1:
                    data1 = data1.replace(b".:!:.test.:!:.", b"")
                regex = b"".join(re.findall(b"\.:!:\.[^{}]+: [^{}]+\.:!:\.", data1))
                if regex:
                    tag_controller(message="{}".format(regex.replace(b".:!:.", b"").decode("utf-8")),
                                   nickname="Server", color="red")
            except (ConnectionResetError, OSError):
                pass

    def receive_file(self):
        global count
        __filename__ = ""
        __filesize__ = 0
        __received__ = 0
        __now__ = 0
        pframe = tk.Frame(master=root)
        pbar = ttk.Progressbar(master=pframe, orient="horizontal", length=200, mode="determinate")
        pstring = tk.StringVar()
        plabel = tk.Label(master=pframe, textvariable=pstring)
        while True:
            try:
                data2 = self.s2.recv(1024 ** 2)
                regex = b"".join(re.findall(b"\.:!:\.[^{}]+&[^{}]+\.:!:\.", data2))
                if regex:
                    filename, filesize = regex.replace(b".:!:.", b"").decode("utf-8").split("&")
                    __filename__ += filename
                    __filesize__ += int(filesize)
                    tag_controller(message="Server wants to send you {}.".format(filename), nickname="Server",
                                   color="red")
                    tag_controller(message="Size: {} byte.".format(filesize), nickname="Size", color="brown")
                    if pframe is None and pbar is None and plabel is None:
                        pframe = tk.Frame(master=root)
                        pframe.pack()
                        pbar = ttk.Progressbar(master=pframe, orient="horizontal", length=200, mode="determinate")
                        pbar.pack(side="left")
                        plabel = tk.Label(master=pframe, textvariable=pstring)
                        plabel.pack(side="left")
                    else:
                        pframe.pack()
                        pbar.pack(side="left")
                        plabel.pack(side="left")
                    __now__ = time.time()
                    time.sleep(1)
                else:
                    if __filename__ == "":
                        pass
                    else:
                        with open("new_{}".format(__filename__), "ab") as f:
                            f.write(data2)
                            __received__ += len(data2)
                            if __filesize__ == __received__:
                                tag_controller(message="{} is received.".format(__filename__),
                                               nickname=__filename__, color="orange")
                                __filename__ = ""
                                __filesize__ = 0
                                __received__ = 0
                                pframe.destroy()
                                pframe = None
                                pbar = None
                                plabel = None
                            else:
                                pbar["value"] = __received__
                                pbar["maximum"] = __filesize__
                                pstring.set("{} %,  {} b/s, {} seconds remaining.".format(
                                    int(100 * __received__ / __filesize__),
                                    int(__received__ / (time.time() - __now__)),
                                    int(__filesize__ / (__received__ / (time.time() - __now__))) - int(
                                        time.time() - __now__)))
            except (ConnectionResetError, OSError):
                if pframe is not None:
                    pframe.destroy()
                    pframe = None
                    pbar = None
                    plabel = None

    def send(self):

        def __send__():
            respond = ".:!:.{}: {}.:!:.".format(__nickname__, str(entry.get()))
            entry.delete("0", "end")
            try:
                self.s1.sendall(bytes(respond.encode("utf-8")))
                tag_controller(message="{}".format(respond.replace(".:!:.", "")), nickname=__nickname__, color="blue")
            except (BrokenPipeError, ConnectionResetError, OSError):
                tag_controller(message="Not connected to the server.")
                self.s1.close()
                self.s2.close()
                self.s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                self.s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                b1.configure(command=connect)

        thread_send = threading.Thread(target=__send__)
        thread_send.start()

    def file_transfer(self):

        def __file_transfer__():
            file = filedialog.askopenfilename(filetypes=[("All Files", ".*")])
            try:
                filename = os.path.basename(file)
                file = open(file, "rb")
                data = file.read()

                def send_file_info():
                    try:
                        self.s2.sendall(bytes(".:!:.{}&{}.:!:.".format(filename, str(len(data))).encode("utf-8")))
                    except (ConnectionResetError, ConnectionAbortedError, BrokenPipeError, OSError):
                        pass

                thread_send_file_info = threading.Thread(target=send_file_info)
                thread_send_file_info.start()
                time.sleep(1)
                while data:
                    try:
                        self.s2.sendall(data)
                        data = file.read()
                    except (ConnectionResetError, BrokenPipeError, IndexError, OSError):
                        pass
                file.close()
            except (TypeError, FileNotFoundError):
                pass

        t2 = threading.Thread(target=__file_transfer__)
        t2.start()


client = Client()


def connect():
    global __nickname__
    if __nickname__ != "":
        b1.configure(command=do_nothing)
        thread_connect = threading.Thread(target=client.__connect__, args=("", 12345))
        thread_connect.start()
    else:
        tag_controller(message="You must create a nickname.")


def create_nickname():
    b2.configure(command=do_nothing)
    __frame__ = tk.Frame(master=root)
    __frame__.pack()
    __entry__ = tk.Entry(master=__frame__)
    __entry__.pack(side="top")
    b7, = buttons("Accept Your Nickname", master=__frame__, side="top")

    def __create_nickname__():
        global __nickname__
        if __entry__.get() == "":
            tag_controller(message="You must write a nickname.")
        else:
            __nickname__ = __entry__.get()
            __frame__.destroy()
            tag_controller(message="Nickname has changed to: '{}'.".format(__nickname__))
            root.title(__nickname__)
            b2.destroy()

    b7.configure(command=__create_nickname__)


def clear():
    global count
    text.configure(state="normal")
    text.delete("1.0", "end")
    text.configure(state="disabled")
    count = 1


def destroy():
    client.s1.close()
    client.s2.close()
    if os.name == "posix":
        import signal
        os.kill(os.getpid(), signal.SIGKILL)
    elif os.name == "nt":
        os.system("TASKKILL /F /PID {}".format(os.getpid()))


b1.configure(command=connect)
b2.configure(command=create_nickname)
b3.configure(command=client.send)
b4.configure(command=clear)
b5.configure(command=client.file_transfer)
b6.configure(command=destroy)

if __name__ == "__main__":
    if os.name == "nt":
        def source_path(relative_path):
            import sys
            base_path = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__)))
            return os.path.join(base_path, relative_path)


        root.iconbitmap(source_path("tkicon.ico"))
    main_thread = threading.Thread(target=root.mainloop)
    main_thread.run()
4 Beğeni

client.py niçin bs4 kullanıyor?

Exception in thread Thread-2:
Traceback (most recent call last):
  File "C:\Users\ONAY\AppData\Local\Programs\Python\Python38-32\lib\threading.py", line 932, in _bootstrap_inner
    self.run()
  File "C:\Users\Scory\AppData\Local\Programs\Python\Python38-32\lib\threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "C:\Users\Scory\Desktop\client.py", line 87, in __connect__
    self.s1.connect((host, port))
OSError: [WinError 10049] İstenen adres içeriğinde geçerli değil

Yok kullanmıyor, sanırım kodlara bir ara bir özellik ekleyecektim. Sonra vazgeçmiş olmalıyım, iki seneye yakındır kodlara bakmadım. Öyle kalmış.

Portu 12345 olarak yazın. Client için de bir port yazma özelliği eklemiştim sonra kaldırmıştım. Kodların son haline göre port doğrudan parametre olarak yazılıyor.

Bu arada kodlardaki bir kaç satırı daha önce değiştirmiştim, o değiştirilen satırlar renklendirme ile alakalıydı. Kodları çalıştırınca, bu değişikliği hatırladım ve eski haline geri getirdim. Bu yüzden yukarıdaki kodları az önce güncelledim. Eğer renklendirme ile ilgili bir bozukluk fark ettiyseniz, kodların güncel halini çalıştırırsanız, o bozukluk ortadan kaybolacaktır.

Selam kardeşim. Emeklerin ve yazdıkların için seni tebrik ederim. Sana bir sorum olacak. Server’da portu belirttikten bağlantıyı sağladıktan sonra client kısmında username ayarlama dışında bir işlem yapamadım serverla bağlantı kurulmadı. Nasıl yapmam gerekir?

Merhaba,

client.py'nin 145. satırında port 12345 olarak yazılmış. Ya o portu elle değiştireceksiniz, ya da server'ın portunu 12345 olarak ayarlamanız gerekiyor.

Veya kodları değiştirip, port girilmesini sağlayan bir widget yazmalısınız. Daha önce vardı böyle bir özellik ama sonra bir ara herhalde kaldırmışım. Bayadır projeyle ilgilenmiyorum doğrusu.

konu ile pek alakalı değil ama client için şöyle bir sistem yazdım ne düşünüyorsunuz?

"""
@author: Efe Osman ASLANOĞLU (PyroSoft)
@date: 8.10.2020
"""
import time
import socket

class Connection:
	def __init__(self, host, port, header=128):
		# Client connection variables
		self.conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		self.host, self.port = host, port 
		self.conn.connect((self.host, self.port))
		self.state = True
		# Constant variables
		self.HEADER = header
	def _send(self, data):
		self.conn.sendall(data)

	def _recv(self, buffer):
		return self.conn.recv(buffer)

	def start(self):
		while self.state:
			try:
			
				send_data = yield  # Get data from outside of function.
				try:
					self._send(send_data) # Short-cut for self.conn.send.
					yield self._recv(self.HEADER)
				except socket.error:

					connected = False

					while (not connected):
						try:
							self.conn.connect((self.host, self.port))
						except:
							time.sleep(2) 
						else:
							connected = True
			except GeneratorExit:
				self.conn.close()
				return self.host, self.conn


# TEST
if __name__ == "__main__":
	client = Connection('localhost', 10000)
	conn   = client.start()
	next(conn)
	conn.send(b'test')
	conn.close()

Burada bir coroutine kullanmışsınız, neden olmasın.

Ayrıca header isimli parametrenin ismini buffer olarak değiştirseniz daha iyi olur.

Önemli olan nokta şu: Sabit bir buffer değeri yazmak yerine, alınacak mesajın uzunluğunu buffer değeri olarak kullanabileceğiniz bir yapı kurmayı deneyin bence. Python’ın dokümanlarında kurmanız gereken bu yapıyla alakalı bir taslak var.

@EkremDincel de bu konuyla alakalı bir gist hazırlamıştı, onu incelemenizde yarar var.

Ayrıca struct kütüphanesini incelemenizde de yarar var. Sunucudan gelecek binary verileri parça parça almanız, örneğin gelen binary verilerin içinde hem gelen mesajın uzunluğunun, hem de mesajın kendisinin paketlenmiş olması, veri transferinin güvenli bir şekilde yapılmasını sağlar. Paketin içindeki mesajın uzunluğunu almak için recv fonksiyonuna yazılacak buffer değeri, @EkremDincel’in yazdığı gibi unsigned short’un boyutu, yani 2 byte olabilir, unsigned short’u ifade eden biçimleyici ise "H" karakteridir. Duruma göre, yani gelen mesajın uzunluğu nispeten büyük olacaksa, biçimlendirme karakterlerinden başkasını da kullanabilirsiniz. Yani mesajın uzunluğu struct ile belirli biçimlendiriciler kullanılarak paketlendiğinde bu paketin uzunluğu o biçimlendiricinin temsil ettiği verinin boyutu kadar olur. 2, 4 veya 8 byte’lık boyuta sahip paketlenmiş byte verisi ulaştıktan sonra gelen veriyi unpack edebilir ve gelen mesajın uzunluk değerini elde edebilirsiniz. Ve hemen ardından da mesajı almak için bu uzunluk değeri ile bir buffer değeri oluşturabilirsiniz.

Mesela, aşağıda linki paylaşılan sayfada yazdığına göre, "!" karakteri, ağ için kullanılan bir biçimlendirme karakteridir ve paketi biçimlendirmede kullanılan stringin ilk karakteri olarak yazılır.

Alternatively, the first character of the format string can be used to indicate the byte order, size and alignment of the packed data, according to the following table:

Mesela basit bir örnek yapalım.

import struct

a = "Hello World"
with open("test", "wb") as f:
    f.write(struct.pack("!H", len(a.encode())) + a.encode())

with open("test", "rb") as f:
    print(struct.unpack("!H", f.read(struct.calcsize("H")))[0] == len(a))

Ayrıca, sizin de vesileniz @EkremDincel’e bir soru sormak isterim.

Sevgili Ekrem kardeşim, microstream’de json kütüphanesine neden ihtiyaç duyduğunu pek anlayamadım, sana zahmet anlamamda yardımcı olur musun?