ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • tkinter & socket
    PYTHON(파이썬)/TKINTER & KIVY 2024. 10. 29. 05:15
    728x90
    반응형

    테스트 SAMPLE PROGRAM

    ##########################################
    #    eIOT - IF Main
    #      Date : 2023.5.4   By: EPLUS
    ##########################################
    import tkinter
    from datetime import datetime
    import time

    import socket
    from _thread import *
    ###################################
    # 함수 정의 ---
    ###################################
    def cmdClose():
        quit()
       
    def displayMsg(window, smsg):
        now = time.strftime("%Y-%m-%d %H:%M:%S")
        stime = time.strftime("%H:%M:%S")    
        icnt = window.listbox.size()
        if icnt==10:
            window.listbox.delete(0,0)    
        window.listbox.insert(icnt, str(stime)+" >> "+ smsg)
        window.listbox.pack(side="left")  
       
    def recv_data(window, client_socket):
        while True :
            data = client_socket.recv(1024)
            sdata = repr(data.decode())
            if len(data) != 0:
                displayMsg(window, sdata)
       
    def sendData(window):
        sip = window.textip.get(1.0,"end")
        sip = sip.replace('\n','')
        sport = window.textport.get(1.0,"end")
        sport = sport.replace('\n','')
        HOST = sip
        PORT = int(sport)
        try:
            client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
            client_socket.connect((HOST, PORT))    
            start_new_thread(recv_data, (window, client_socket,))
            smsg = "Send Data"
            client_socket.send(smsg.encode())        
        except:
            displayMsg(window, "Socket 접속오류!!!")
        #
       
    ###################################
    # 화면 정의 및 Start
    # => 향후 쓰레드 검토 : threading
    ###################################  
    class Application(tkinter.Frame):
        def __init__(self, master):
            super().__init__(master)
            self.timer = None
            self.master = master
            self.master.title("eIOT_MAIN_V1.0")
            self.pack(fill='both', expand=True)

            now = time.strftime("%Y-%m-%d %H:%M:%S")
            # Frame 설정 - 상단, 하단
            self.frame = tkinter.Frame(self, relief="solid", bg="white", bd=1)
            self.frame.pack(side="top", fill="x", expand=False)
           
            self.frameB = tkinter.Frame(self, relief="solid", bg="yellow", bd=1)
            self.frameB.pack(side="bottom", fill="x", expand=False)        
            # Button 설정 - Start & 종료 버튼
            self.button = tkinter.Button(self.frame, overrelief="solid", width=10, relief="raised", font="굴림체", height=1, command=cmdClose, text="종료" )
            self.button.pack(side="right")
           
            # Label
            sdate = time.strftime('%Y-%m-%d')
            self.label = tkinter.Label(self.frame, text="일자 : "+sdate, width=20, height=1, bg="white", bd=2, font="굴림체", relief="flat" )
            self.label.pack(side="left")
           
            self.labelM = tkinter.Label(self.frameB, text="", width=200, height=2, bg="yellow", relief="solid" )
            self.labelM.pack(side="left")        
            # ListBox
            self.listbox = tkinter.Listbox(self, selectmode='extended', font="굴림체", fg="white", bg="black", bd=1, width=760)

            # Text
            self.textport = tkinter.Text(self.frame, width=5, height=1, font="굴림체", bg="yellow")
            self.textport.pack(side="right")

            self.textip = tkinter.Text(self.frame, width=18, height=1, font="굴림체", bg="yellow")
            self.textip.pack(side="right")
           
            sip = self.getIp()
            sport = self.getPort()
            self.textip.insert("current", sip)
            self.textport.insert("current", sport)
            self.main()
               
        def startTimer(self, *_):
            self.main()
       
        def stopTimer(self, *_):
            self.after_cancel(self.timer)
           
        def getIp(self):
            sip = ""
            file = open("mip.txt",'r')
            sip = file.read()    
            sip = sip.replace('\n','')    
            return sip

        def getPort(self):
            sport = ""
            file = open("mport.txt",'r')
            sport = file.read()        
            sport = sport.replace('\n','')    
            return sport

        def main(self):
            now = time.strftime("%Y-%m-%d %H:%M:%S")
            stime = time.strftime("%H:%M:%S")
            # 소켓 전송
            sendData(self)
            self.labelM.config(text=str(now))
            #
            self.timer = self.after(1000, self.main)

    # Main
    root = tkinter.Tk()
    root.geometry("760x290+1+1")
    #
    app = Application(root)
    #
    app.mainloop()




    ChatGPT가 분석한 내용

    이 코드는 TkinterGUI를 이용하여 소켓 통신을 수행하는 기능입니다. 주요은 GUI 인터페이스를 통해 특정 IP와 포트에 연결하고 메시지를 제공하는 것입니다. 다음은 이 코드의 주요 구성요소와 기능에 대한 분석입니다.

    주요 구성 요소 및 기능

    1. Tkinter 프레임워크 사용 :
      • GUI를 생성하기 위해 Tkinter사용했습니다.
      • Tkinter.Frame, Tkinter.Button, Tkinter.Label등의 요소를 활용하여 UI를 구축하고 있습니다.
      • 부분은 기본적으로 두 개의 프레임으로 나누어져 하위 상단과 하단으로 구성됩니다.
    2. 클래스와 함수 구조 :
      • Application클래스는 Tkinter.Frame사용자를 대신하여 UI를 정의하고 실행하는 역할을 합니다.
      • 주요 문자열은 cmdClose(), displayMsg(), recv_data(), sendData(), startTimer(), stopTimer(), getIp(), getPort(), main()이 있습니다.
    3. 소켓 통신 :
      • 소켓을 통해 서버와 통신하는 기능이 있습니다.
      • sendData()JSON에서 IP와 포트 정보를 담당 서버에 소켓을 연결하고, 데이터를 제공합니다.
      • 소켓 연결 후 수신 상태를 유지하기 위해 recv_data()인증을 보호의 스레드로 실행합니다( start_new_thread사용).
    4. 스레드 사용 :
      • 데이터를 수신하기 위해 특수한 스레드를 사용하여 데이터를 처리합니다.
      • start_new_thread()함수가 사용되어 데이터를 전송하는 스레드를 생성합니다. 이 스레드는 데이터가 수신될 때마다의 메시지를 리스트박스에 추가합니다.
    5. 타이머 기능 :
      • main()JSON은 매 1초마다 호출되어 소켓 연결을 시도하고 현재 시간을 라벨에 표시하는 타이머 기능을 포함합니다.
      • after()함수를 이용하여 작업 시간을 반복적으로 실행합니다.
    6. 텍스트의 IP와 포트 정보 읽기 :
      • getIp(), getPort()함수에서 파일을 입력하는 IP와 포트를 가져옵니다 mip.txt.mport.txt
      • 이 정보는 Text표시됩니다.

    코드 분석 및 문제점

    1. 소켓 연결 오류 :
      • 만약 소켓 연결이 실패할 경우에는 except오류 메시지를 displayMsg()통해 블록을 반환하지만, 반복적으로 연결을 시도하면서 CPU를 많이 소모할 가능성이 있습니다.
    2. 목록 크기 제한 :
      • displayMsg()콜롬비아에서 리스트박스의 항목을 최대 10개로 제한하고, 초과하면 첫 번째 항목을 삭제합니다.
      • 이 방식은 메모리 사용을 줄이는 데 도움을 줄 수 있지만 더 많은 로그를 제외하는 경우가 있을 수 있습니다.
    3. 데이터 기능 제한 :
      • sendData()호소에서 연락이 고정된 문자열 "Send Data"입니다.
      • 사용자가 직접 메시지를 입력할 수 있도록 수정하면 더 유용하게 활용될 수 있습니다.
    4. 발생 처리 미흡 :
      • 소켓의 처리 부분은 비교적 비슷합니다. 예를 들어, 연결하지 못함 시 재시도 전략이나, 네트워크 상태에 대응하는 방법 등은 없습니다.
    5. UI 업데이트와 네트워크 통신 :
      • UI 업데이트와 네트워크 통신은 동일한 메인 스레드에서 작동하고 있어 응답성이 떨어질 수 있습니다.
      • 네트워크 통신을 별도의 스레드에서 처리하고, UI는 메인 스레드에서 유지하는 방식으로 수정하는 것이 권장됩니다.
    6. 보안 문제 :
      • IP 주소와 포트 번호를 텍스트 파일로 저장하고 입력하는 방식은 보안에 있을 수 있습니다.
      • 다양한 기능을 설정하여 파일로 파일을 저장하는 등의 보안 강화가 필요합니다.

    개선 방향

    • UI와 통신의 분리 : 현재 코드에서는 UI 스레드와 네트워크 통신이 작은 루프에서 동작하는 구조입니다. 네트워크 통신은 별도의 스레드에서 수행하고, UI 스레드와 감시로 변경하여 작업의 응답성을 즐길 수 있습니다.
    • 처리 강화 : 소켓 연결 실패 시 일정 시간을 재시도하도록 처리를 강화할 수 있습니다. 이 서비스는 계속해서 연결될 수 있습니다.
    • 사용자 입력 기능 추가 : 메시지를 직접 입력하고 할 수 있는 텍스트 상자를 추가하면 사용자와 결합된 복합이 복합될 것입니다.
    • 로그 추가 :리스트박스에 로그인을 허용하는 파일에 저장하는 기능을 추가하여 로그를 나중에 참조할 수 있도록 할 수 있도록 할 것입니다.

    이 코드의 주요 기능은 네트워크 통신과 로그인 기록을 통해 GUI를 통해 간단히 보여주는 것입니다. 독립 통신 부분과 UI 부분의 분리가 필요하고 처리할 수 있는 강화 기능이 있어야 더 특별할 수 있습니다.

    728x90

    'PYTHON(파이썬) > TKINTER & KIVY' 카테고리의 다른 글

    kivy로 윈도우용 GUI 구현하기  (0) 2024.10.29
    GUI 툴 kivy란? (크로스 플랫폼)  (8) 2024.10.29
    tkinter를 APP로 전환은?  (1) 2024.10.29
    tkinter & opencv  (0) 2024.10.29
    tkinter (GUI)  (0) 2024.10.29
Designed by Tistory.