본문 바로가기
First step/AI 기초반

[TIL]21.07.20TCP/IP 기초 예외처리

by Joshua21 2021. 7. 20.

오늘은 socket통신의 기초를 배웠다 먼저 

 

#오른쪽 server
import socket
#서버의 주소 , hostname 또는 ip address를 사용할수 있음
HOST = '127.0.0.1'

#서버에서 지정해 놓은 포트 번호
PORT = 9999

server_socket= socket.socket(socket.AF_INET,socket.SOCK_STREAM)

#오류가발생했을떠 처리하기위해 필요
server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)


server_socket.bind((HOST,PORT))


server_socket.listen()

print('server listen')

client_socket,addr=server_socket.accept()

print('connetced by',addr)




while True:

    data = client_socket.recv(1024)

    if not data: #수신한 데이터가 빈칸이면 break
        break

    print('Receiced from', addr, data.decode())


    client_socket.sendall(data)

client_socket.close()
server_socket.close()

 

#왼쪽 client

import socket

HOST='127.0.0.1'

PORT=9999

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

#지정한 host 와 port를사용하여 서버에접속
client_socket.connect((HOST,PORT))

#메세지를 전송합니다.
client_socket.sendall(('안녕'.encode()))

#메세지를 수신합니다
data = client_socket.recv(1024)
print('Received', repr(data.decode()))


#소켓을 닫습니다.
client_socket.close()

 

thread 없이 서버와 클라이언트가1대1로 연결되는 방식을 연습했고 그다음으로

#오른쪽 서버

import socket
from _thread import *
from pynput import keyboard

#쓰레드에서 실행되는 코드입니다.
#접속한클라이언트마다새로운 쓰레드가 생성되어 통신을 하게 됩니다.
def threaded(client_socket, addr):
    print('connected by :' + addr[0], ':', addr[1])
    #클라이언트가 접속을 끊을 때 까지 반복합니다.
    while True:
        try:
            #데이터가 수신되면 클아이언트에 다시 전송합니다.(에코)
            data= client_socket.recv(1024)
            if not data:
                print('disconnected by' + addr[0], ':', addr[1])
                break
            print('Received from'+addr[0], ':', addr[1],data.decode())
            client_socket.send(data)
        except ConnectionResetError as e:
            print('DIsconnected by ' + addr[0], ':', addr[1])
            break 
    client_socket.close()


HOST ='127.0.0.1'
PORT=9999
server_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
server_socket.bind((HOST,PORT))
server_socket.listen()

print('server start')

#클라이언트가 접속하면 accept 합수에서 새로운소캣을 리턴합니다
#새로운 쓰래드에서 해당 소켓을 사용하여 통신을 하게 됩니다.
while True:
    print('wait')
    client_socket, addr = server_socket.accept()
    start_new_thread(threaded,(client_socket,addr))
server_socket.close()

#왼쪽 클라이언트

import socket

HOST ='127.0.0.1'
PORT=9999
client_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client_socket.connect((HOST,PORT))

#키보드로 입력한문자열을 서버로 전송하고
#서버에서 에코되어 돌아오는 메세지를 받으면 화면에 출력합니다.

while True:

    message=input('Enter Message:')
    if message=='quit':
        break

    client_socket.send(message.encode())
    data=  client_socket.recv(1024)


    print('Receiced from the server :' , repr(data.decode()))
client_socket.close()

서버하나로 다중 클라이언트와 연결되는것을 연습해보았다.

 

import socket
from _thread import*
from pynput import keyboard
import time
import threading
import sys

bLoopEnd=False

def Mainloop():
    if(bLoopEnd==False): #키보드 이벤트인 on_release에서 ESC가눌리면 bloop상태변화
        threading.Timer(0.1,Mainloop).start()
    else:
        print('server close')
        server_socket.clsoe()
        sys.exit()
        
# def on_press(key):
#     try:
#         print('Alophanumeric key pressed: {0}'.format(kye.char))
        
#     except AttributeError:
#         print('special key pressed: {0}'.format(key))

def on_release(key):
    global bLoopEnd #전역 변수 bLoopEnd 사용 
    if  key == keyboard.key.esc:
        print("=====esc=====")
        bLoopEnd=True
        return False
#쓰레드에서 실행되는 코드
def clientchkThreaded(i):
    while True:
        print('clientChkThreaded wait!!')
        client_socket, addr=server_socket.accept() #새로은 client가 접속할떄까지 대기
        
        print('client_socket connected!!',addr)
        threaded(client_socket,addr)
#접속한 클라이언트마다 새로운 쓰레드가 생성되어 통신하게 됩니다.
def threaded(client_socket,addr):
    print('connected by : ',addr[0],':',addr[1])
    while True:
        try:
            #데이터가 수신되면 클라이언트에 다시 전송합니다.(에코)
            data=client_socket.recv(1024)
            
            if not data:
                print('Disconnected by '+ addr[0],':',addr[1])
                break
            print('Received from'+addr[0],':',addr[1],data.decode())
            
            client_socket.send(data)
            
        except ConnectionResetError as e:
            print('Disconnected by'+addr[0],':',addr[1])
            break
    
    print('end')
    client_socket.close()
    
    
HOST ='127.0.0.1'
PORT=9999
server_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
server_socket.bind((HOST,PORT))
server_socket.listen()

print('server start')

i=0
start_now_thread(ClientChkThreaded,(i,))
MainLoop()

#keayboaerd listner를 등록 colletc events until released
with keyboard.Listener(on_press=on_press,on_release=on_release)as listener:
    lintener.join()
    
#리스너 등록방법2    
# listener=keyboard.Listener(on_press=on_press,on_release=on_release)
# listener.start()
# listener.join

 

다음으로 예외처리를 배웠다

 

y=[10,20,30]
try:
    index,x=map(int,input('인덱스와 나눌 숫자를 입력하세요 :').split())
    print(y[index]/x)
    
except ZeroDivisionError as e:
    print('0으로 나눌수 없습니다.',e)
    
except IndexError as e:
    print('잘못된 인덱스 입니다.',e)

 

y=[10,20,30]
try: #실행할 코드
    x=int(input('나눌 숫자를 입력하세요 : '))
    y=10/x
    
except ZeroDivisionError as e: #예외가 발생했을때 처리하는 코드
    print('0으로 나눌수 없습니다.',e)
    
else: #예외가 발생하지 않았을때 실행할 코드
    print(y)
finally:#예외 발생여부와 상관없이 항상 실행할 코드
    print('코드 실행이 끝났습니다.')
    

 

#raise 예외 발생 시키기
try:
    x=int(input('3의 배수 입력: '))
    if x%3!=0:
        raise Exception('3의 배수가 아닙니다.')
        
    print(x)
except Exception as e:
    print('예외가 발생',e)

 

#raise를 사용하지만 함수 안에는 try,except가 없는 상태
def three_multiple():
    x=int(input('3의배수를 입력하세요 :'))
    if x%3 !=0:
        raise Exception('3의 배수가 아닙니다.')
    print(x)
try:
    three_multiple()
except Exception as e :
    print('예외가 발생했습니다',e)

 

def three_multiple():
    try:
        x=int(input('3의배수를 입력하세요 :'))
        if x%3 !=0:
            raise Exception('3의 배수가 아닙니다.')
        print(x)
    except Exception as e:
        print('three_multiple 함수에서 예외가 발생했습니다.',e)
        raise 
        
        
try:
    three_multiple()
except Exception as e:
    print('스크립트 파일에서 예외가 발생했습니다.',e)

 

def three_multiple():
    try:
        x=int(input('3의배수를 입력하세요 :'))
        if x%3 !=0:
            raise Exception('3의 배수가 아닙니다.')
        print(x)
    except Exception as e:
        print('three_multiple 함수에서 예외가 발생했습니다.',e)
        raise RuntimeError('three_multiple 함수에서 예외가 발생했습니다.')
                
try:
    three_multiple()
except Exception as e:
    print('스크립트 파일에서 예외가 발생했습니다.',e)

 

RuntimeError는 TypeError, NameError 와 같이 에러의종류이다.

#예외 만들기
class NotThreeMultipleError(Exception):
    def __init__(self):
        super().__init__('3의 배수가 아닙니다.')
def three_multiple():
    try:
        x=int(input('3의 배수를 입력하세요 : '))
        if x%3 !=0:
            raise NotThreeMultipleError
        print(x)
        
    except Exception as e:
        print('예외가 발생했습니다.',e)
        
three_multiple()