320x100

 

 

# 서버코드
import socket
import argparse
import threading
import time

user_list = {}

def handle_receive(client_socket, addr, user):
    while 1:
        data = client_socket.recv(1024)
        data = data.decode()

        if data == "/종료" or data == "/exit" : break        
        print(user,data)

        #받은 데이터를 모든 클라이언트에게 전송한다.
        for con in user_list.values():
            try:
                con.sendall(data.encode())
            except:
                print("클라이언트 소켓 에러")

    del user_list[user]
    client_socket.close()

if __name__ == '__main__':

    host = "host_ip" #127.0.0.1
    port = 4000

    #IPv4 체계, TCP 타입 소켓 객체를 생성
    # socket.AF_INET: 해당 소켓을 IP version 4 용으로 사용하겠다는 의미
    # socket.SOCK_STREAM: 해당 소켓에 TCP 패킷을 받겠다는 의미
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    #포트를 사용 중 일때 에러를 해결하기 위한 구문
    #기본적으로 socket을 사용하고 나면 사용한 port는 close로 닫아주는게 맞다.
    #그래야 해당 port를 다른데서도 사용할 수 있으니깐.
    #근데 port를 닫았다고해도 일정시간 동안은 TIME_WAIT 상태로 대기한다고 한다.
    #그리고 이 상태에서는 즉각적으로 다시 바로 사용할 수 없다.
    #그래서 socket을 쓰고 close를 했는데도 already in use 에러가 발생하게된다.
    #이런 에러를 막기위해서 setsockopt을 사용한다. 사용법은 아래와 같다.
    #socket.SO_REUSEADDR: 방금 사용하고 close한 port를 즉시 다시 사용한다는 의미
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    #ip주소와 port번호를 함께 socket에 바인드 한다.
    #포트의 범위: 1~65535
    server_socket.bind((host, port))
    server_socket.listen(5)# 클라이언트 최대 접속 수

    print('채팅서버를 시작합니다.')
    while 1:
        try:
            #클라이언트 함수가 접속하면 새로운 소켓을 반환한다.
            client_socket, addr = server_socket.accept()#클라이언트 접속까지 대기함
        except:            
            #의도하지 않은 서버 종료에 대한 예외 처리
            #프로그램 중단시 모든 클라이언트 소켓들 닫기.
            for user, con in user_list:
                con.close()
            server_socket.close()            
            break

        user = client_socket.recv(1024)
        user = user.decode()
        print(user,'서버에 접속하였습니다.')
        user_list[user] = client_socket
                        
        #daemon 속성은 서브쓰레드가 데몬 쓰레드인지 아닌지를 지정하는 것인데,
        #데몬 쓰레드란 백그라운드에서 실행되는 쓰레드로 메인 쓰레드가 종료되면 즉시 종료되는 쓰레드이다.
        #반면 데몬 쓰레드가 아니면 해당 서브쓰레드는 메인 쓰레드가 종료할 지라도 자신의 작업이 끝날 때까지 계속 실행된다.
        receive_thread = threading.Thread(target=handle_receive, args=(client_socket, addr,user))
        receive_thread.daemon = True
        receive_thread.start()
import socket
import threading

def handle_receive(client_socket, user):
    while True:
        try:
            data = client_socket.recv(1024)#데이터가 수신될 때까지 대기함
        except:
            print("연결 끊김")
            break
        data = data.decode()#바이트 타입의 데이터를 decode()로 문자열로 변환
        if not user in data:#자신의 데이터를 제외한 나머지 데이터를 출력함
            print(data)

def handle_send(client_socket, user):
    while True:        
        data = input()#사용자로부터 문자열을 입력받는 함수
        #데이터는 encode()함수를 이용하여 바이트형으로 변환
        client_socket.sendall(data.encode())#소켓을 통해 서버로 데이터 보내기
        if data == "/종료" or data == "/exit": break
    client_socket.close()
    print('소켓 닫기')


if __name__ == '__main__':
    
    port = 4000 # 포트넘버
    host = 'server_ip' #서버 IP #127.0.0.1
    user = 'user_id'

    #IPv4 체계, TCP 타입 소켓 객체를 생성
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 지정한 host와 prot를 통해 서버에 접속합니다.
    client_socket.connect((host, port))

    # 문자열을 전송할 때 encode()을 이용한다. 파이썬 문자열의 encode() 메소드는 문자열을 byte로 변환해주는 메소드이기 때문이다.
    # 파이썬 내부에서 다뤄지는 문자열은 파이썬에서 생성된 객체이고, 이를 바로 트랜스포트에 그대로 싣는 것은 불가능합니다.
    # 그러므로 적절한 인코딩을 하여 보내야만 합니다.
    # 만약 encode()을 사용하지 않을 경우 에러가 발생 한다. 
    client_socket.sendall(user.encode())

    receive_thread = threading.Thread(target=handle_receive, args=(client_socket, user))
    receive_thread.daemon = True
    receive_thread.start()

    send_thread = threading.Thread(target=handle_send, args=(client_socket, user))
    send_thread.daemon = True
    send_thread.start()

    #join()은 부모쓰레드가 자식 쓰레드가 종료될 때까지 기다려준다.
    #즉 전체 프로그램의 실행이 하나의 쓰레드이고 부모쓰레드가 되며,
    #먼저 send_thread, receive_thread가 종료된후 프로그램이 종료하게 된다.
    send_thread.join()    
    receive_thread.join()
반응형
320x100

even though  비록 ~ 이지만 : 사실이 아닌 가정을 나타냄

 - ex) Even though I passed the test, I didn't leave here

내가 그 시험을 통과 했지만, 여기를 떠나지 않았다.

 

even if  비록 ~ 일지라도 : 실제 사실을 나타냄

 - ex) Even if I pass the test, I won't leave here.

내가 그 시험을 통과할지라도, 나는 여기를 떠나지 않을 것이다.

 

반응형

'영어' 카테고리의 다른 글

get there 뜻 예제  (0) 2024.05.04
receive, get 차이  (0) 2023.09.02
It's been ~ 시간이 흘렀다. 는 표현  (0) 2022.06.28
work out , exercise 차이  (0) 2022.06.27
출근하다 영어 표현  (0) 2022.06.27
320x100

It's (It has) been 시간 (since ~): (~이래로) 시간이 흐르다.

 

It's been 2 hours: 2시간이 흘렀다.

It's been over 10 years: 10년이 넘었다.

It's been a while: 시간이 꽤 흘렀네~!.

 

It's been over 10 years since we broke up.: 우리가 헤어진 후로 10년이 넘었어.

It's been already a year since we started studying English together: 우리가 함께 영어공부를 시작한지 벌써 1년이 되었어요.

 

 

 

 

반응형

'영어' 카테고리의 다른 글

get there 뜻 예제  (0) 2024.05.04
receive, get 차이  (0) 2023.09.02
even though 와 even if 차이  (1) 2023.08.22
work out , exercise 차이  (0) 2022.06.27
출근하다 영어 표현  (0) 2022.06.27
320x100

work out 과 exercise 는 둘 다 '운동하다 ' 라는 뜻을 가짐.

 

차이점

work out : (헬스장에서) 운동하는 것을 의미함.

 

exercise: 일반적인 운동에 대한 표현에서 사용됨. 걷기, 조깅 등....

반응형

'영어' 카테고리의 다른 글

get there 뜻 예제  (0) 2024.05.04
receive, get 차이  (0) 2023.09.02
even though 와 even if 차이  (1) 2023.08.22
It's been ~ 시간이 흘렀다. 는 표현  (0) 2022.06.28
출근하다 영어 표현  (0) 2022.06.27
320x100

나는 (교통수단)로 출근한다.

 

 

예제 문장

1. 나는 버스타고 출근한다.

- I take a bus to work.

- I go to work by bus.

 

2. 나는 걸어서 출근한다.

- I walk to work.

- I go to work on foot.

- I go to work by walking.

 

 

 

 

반응형

'영어' 카테고리의 다른 글

get there 뜻 예제  (0) 2024.05.04
receive, get 차이  (0) 2023.09.02
even though 와 even if 차이  (1) 2023.08.22
It's been ~ 시간이 흘렀다. 는 표현  (0) 2022.06.28
work out , exercise 차이  (0) 2022.06.27
320x100

아래 이미지 파일을 다운로드 & 소스와 같은 폴더에 복사후 실행하기 바랍니다.

arrow.png
0.32MB

 

protocol() 함수는 이벤트와 함수를 연결하는 기능을 하며 아래 코드에는 위도우 창 닫기 이벤트(WM_DELETE_WINDOW)와 on_closing() 함수를 연결하여, 윈도우 창을 닫을 때 on_closing() 함수를 호출합니다.

 

from tkinter import *


class StageCanvas:
    def __init__(self,window):
        self.window = window
        self.canvas=Canvas(self.window, bg ="white") # game scene canvas
        self.canvas.create_text(320,300,font="Times 15 italic bold",text="Backspace 키 메뉴로 돌아가기")
        self.canvas.create_text(320,360,font="Times 15 italic bold",text="Stage Scene")
        

    def display(self):
        pass

    def pack(self):
        self.canvas.pack(expand=True, fill=BOTH)

    def unpack(self):
        self.canvas.pack_forget()

    def keyReleaseHandler(self, event):
        if event.keycode == 8:
            return 0
        else:
            return -1

    def destroy(self):
        self.canvas.destroy()


class MenuCanvas:
    def __init__(self,window):
        self.window = window
        self.menu_idx = 0

        self.canvas=Canvas(self.window, bg ="white")# menu canvas

        self.canvas.create_text(320,360,font="Times 15 italic bold",text="Scene Change")
                
        self.canvas.create_text(320,160,font="Times 15 italic bold",text="Start")
        self.canvas.create_text(320,200,font="Times 15 italic bold",text="Option")
        self.canvas.create_text(320,240,font="Times 15 italic bold",text="Exit")


        self.arrowimg = PhotoImage(file="arrow.png").subsample(20)
        self.arrow = self.canvas.create_image(250,160, image = self.arrowimg,tags="arrow")


    def display(self):
        pass
        

    def pack(self):
        self.canvas.pack(expand=True, fill=BOTH)

    def unpack(self):
        self.canvas.pack_forget()


    def keyReleaseHandler(self, event):
        if event.keycode == 38 and self.menu_idx > 0: # up direction key
            self.menu_idx = self.menu_idx - 1
            self.canvas.move(self.arrow, 0, -40)
            return -1
        elif event.keycode == 40 and self.menu_idx < 2: # down direction key
            self.menu_idx = self.menu_idx + 1
            self.canvas.move(self.arrow, 0, 40)
            return -1
        elif event.keycode == 32:
            return self.menu_idx


    def destroy(self):
        self.canvas.destroy()




class SceneChange:
    def __init__(self):
        self.window = Tk()
        self.window.title("장면전환")
        self.window.geometry("640x480")

        self.window.protocol("WM_DELETE_WINDOW", self.on_closing)

        self.scene_idx = 0
        
        self.stage = StageCanvas(self.window)
        self.menu = MenuCanvas(self.window)
        self.menu.pack()


        self.canvas_list = []
        self.canvas_list.append(self.stage)
        self.canvas_list.append(self.stage)

        self.window.bind("<KeyPress>",self.keyPressHandler)
        self.window.bind("<KeyRelease>",self.keyReleaseHandler)

        while True:
            #
            #
            for canvas in self.canvas_list:
                canvas.display()


            self.window.after(33)
            self.window.update()

    def on_closing(self):
        for canvas in self.canvas_list:
            canvas.destroy()

        self.window.destroy()

    def keyReleaseHandler(self, event):

        result = -1

        if self.scene_idx == 0:
            result = self.menu.keyReleaseHandler(event)

        elif self.scene_idx == 1:
            result = self.stage.keyReleaseHandler(event)

        if self.scene_idx == 0 and result==0:
            self.scene_idx = 1
            self.menu.unpack()
            self.stage.pack()

        elif self.scene_idx==1 and result==0:
            self.scene_idx = 0
            self.menu.pack()#메뉴 canvas 나타남
            self.stage.unpack()# Main 장면 canvas 사라짐
                
    def keyPressHandler(self,event):
        print(event.keycode)


SceneChange()
반응형

+ Recent posts