순천향대학교컴퓨터공학과 이상정 순천향대학교컴퓨터공학과 1 학습내용 인터넷구조 인터넷구성요소 인터넷주소 클라이언트 / 서버구조 소켓프로그래밍소개 파이썬소켓프로그래밍 TCP 클라이언트 / 서버프로그래밍 쓰레드소개 파이썬쓰레드 채팅클라이언트 / 서버프로그램 네트워크그리드셀예 네트워크연결그리드그리기 순천향대학교컴퓨터공학과 2
구성요소로본인터넷 (1) 호스트 (host), 종단시스템 (end system) 컴퓨터네트워크에연결된컴퓨팅장치 네트워크응용들을수행 통신링크 (communication link) 동축케이블, 광케이블, 구리선, 전파, 위성 다양한전송률 (transmission rate, 또는 bandwidth) 로데이터 ( 패킷 ) 전송 패킷스위치 (packet switch) 라우터 (router), 스위치 (switch) 패킷을전달 순천향대학교컴퓨터공학과 3 구성요소로본인터넷 (2) 인터넷 (Internet) 네트워크들의네트워크 (network of networks) 프로토콜 (protocol) 정보 ( 메시지 ) 의송수신을제어 예 TCP(Transmission Control protocol), IP(Internet Protocol), HTTP, SMTP, 이더넷 (Ethernet) 순천향대학교컴퓨터공학과 4
네트워크요소 네트워크가장자리 (edge) 호스트 : 클라이언트와서버 데이터센터내의서버들 접속네트워크 (access network), 물리매체 (physical media) 유무선통신링크 네트워크코어 (core) 라우터 네트워크들의네트워크 순천향대학교컴퓨터공학과 5 클라이언트 / 서버구조 서버 (server) 항상켜져있는호스트 서비스제공 고정 IP 주소 데이터센터로확장 클라이언트 (client) 서버와통신 서비스요청 클라이언트들간직접통신하지않음 유동 IP 가질수있음 항상연결되어있지않고간헐적으로통신할수있음 순천향대학교컴퓨터공학과 6
인터넷주소 인터넷주소는 IP 주소와포트번호로구분 IP 주소 호스트 / 라우터주소 IPv4 주소 : 32 비트 32 비트 IP 주소공간이빠른속도로고갈되어가고있음 => IPv6: 128 비트 포트번호 호스트내의프로세스 ( 프로그램 ) 을구분하는번호 예 HTTP 서버 : 80, 메일서버 : 25 인터넷표준프로토콜에대한알려진 (well-known) 포트번호리스트는 www.iana.org 참조 순천향대학교컴퓨터공학과 7 소켓 (Socket) 프로세스는소켓 (socket) 을통해네트워크로메시지를송수신 소켓은호스트의애플리케이션계층과트랜스포트계층간의인터페이스 프로세스는집 (house), 소켓은출입구 (door) 에비유 송신프로세스는출입구 ( 소켓 ) 바깥네트워크로메시지를밀어냄 소켓은애플리케이션과네트워크사이의 API(Application Programming Interface) 순천향대학교컴퓨터공학과 8
소켓프로그래밍 두가지형태의트랜스포트서비스 UDP: 비연결형, 비신뢰적인데이터전송 TCP: 연결형, 신뢰적인데이터전송 TCP 소켓프로그래밍 서버프로세스가먼저수행중에있어야함 서버는클라이언트의초기접속을처리하는소켓을생성해야함 클라이언트는서버에초기접속 클라이언트는 TCP 소켓을생성하고, 서버프로세스의 IP 주소와포트번호를명시하여서버에접속 서버는클라이언트에의해초기접속클라이언트와통신하는서버프로세스를위한새로운소켓 ( 연결소켓 ) 을생성 서버와클라이언트가데이터송수신 순천향대학교컴퓨터공학과 9 TCP 클라이언트 / 서버소켓상호동작 순천향대학교컴퓨터공학과 10
TCP 클라이언트 / 서버소켓상호동작 파이썬 순천향대학교컴퓨터공학과 11 파이썬소켓 소켓생성 소켓라이브러리 : socket 모듈 소켓생성 socket.socket(family, type, proto=0) 함수 : return socket family: 프로토콜표시, 인터넷인경우 AF_INET type: 인터넷인경우트랜스포트서비스표시 TCP: SOCK_STREAM, UDP: SOCK_DGRAM socket 객체를리턴 TCP 소켓생성예 serversocket = socket(af_inet, SOCK_STREAM) STREAM) 소켓종료 socket.close() close() 메소드 순천향대학교컴퓨터공학과 12
파이썬소켓 서버연결초기화 주소와소켓결합 서버의주소 (IP 주소, 포츠번호 ) 를생성된소켓과결합 socket.bind(address) 메소드 address: (host IP 주소, 포트 ) 튜플 연결요청청취 튜플 (tuple) 은리스트와거의비슷하나리스트와달리요소의변경 ( 추가, 삭제등 ) 할수없음 클라이언트로부터소켓연결요청을청취 socket.listen(backlog) 메소드 backlog: 허용되는최대요청수 연결수락 클라이언트의연결요청을수락 socket.accept() 메소드 : return (socket, address) 클라이언트와통신을위한새로운연결소켓과클라이언트의주소를리턴 순천향대학교컴퓨터공학과 13 파이썬소켓 서버연결초기화예 서버연결초기화예 서버의 IP 주소가 '229.78.56.90' 이라고가정 서버인경우 IP 주소생략가능, ' ' 7000 번포트번호로클라이언트의연결요청을청취하는예 # 호스트주소지정 servername = '229.78.56.90'' serverport = 7000 # 소켓생성 serversocket = socket(af_inet, SOCK_STREAM) # 주소와소켓결합 serversocket.bind((servername, serverport)) # 연결요청청취 serversocket.listen(5) # 연결요청수락, 연결소켓생성 connectionsocket, addr = serversocket.accept() 순천향대학교컴퓨터공학과 14
파이썬소켓 클라이언트연결초기화 서버에연결요청 서버에연결을요청 socket.connect(address) 메소드 address는서버주소 (IP, 포트 ) # 연결할서버주소지정 servername = '229.78.56.90' serverport = 7000 # 소켓생성 clientsocket = socket(af_inet, SOCK_STREAM) # 서버에연결요청 clientsocket.connect((servername, serverport)) 순천향대학교컴퓨터공학과 15 파이썬소켓 데이터송수신 데이터송신 socket.send(bytes) 메소드 : return bytes_num bytes: 보내질바이트데이터들 보내진데이터의바이트수리턴 데이터수신 socket.recv(bufsize) 메소드 : return bytes bufsize: 한번에받을수있는최대데이터의바이트수 받은데이터의바이트들리턴 data = input('input string: ') clientsocket.send(data.encode("utf8")) # 문자열인코드하여송신 data = clientsocket.recv(1024) # 데이터수신 print(data) 순천향대학교컴퓨터공학과 16
TCP 소켓프로그램예소개 1. 클라이언트는키보드로한줄의문자 ( 데이터 ) 를읽고, 그데이터를서버로송신 2. 서버는데이터를수신하고, 문자를대문자로변환 3. 서버는수정된데이터를클라이언트에게송신 4. 클라이언트는수정된데이터를수신하고화면에출력 한컴퓨터에서 2 개의파이썬셀수행하여클라이언트 / 서버 통신 자기자신을나타내는루프백 (loopback) 주소사용 127.0.0.1 윈도우에서자기자신의주소를알려면콘솔창에서 ipconfig 명령 c> ipconfig 순천향대학교컴퓨터공학과 17 TCP 프로그램예 서버프로그램 ### TCP 서버프로그램 from socket import * # 네트워크 TCP 연결초기화 print("server TCP initialize...") # 호스트주소지정 serverport = 7000 # 서버소켓생성 serversocket = socket(af_inet, SOCK_STREAM) # 주소와소켓결합 serversocket.bind(('', serverport)) # 연결요청청취 serversocket.listen(1) while True: # 연결요청수락, 연결소켓리턴 connectionsocket, addr = serversocket.accept() print("client connected...", addr) # 데이터수신 rawdata = connectionsocket.recv(1024) print("receive: ", rawdata) # 대문자변환 upperstr = rawdata.upper() # 데이터송신 connectionsocket.send(upperstr) connectionsocket.close() 순천향대학교컴퓨터공학과 18
TCP 프로그램예 클라이언트프로그램 ### TCP 클라이언트프로그램 from socket import * # 네트워크 TCP 연결초기화 print("client TCP initialize...") # 연결할서버주소지정 servername = '127.0.0.1' serverport = 7000 # 클라이언트소켓생성 clientsocket = socket(af_inet, SOCK_STREAM) # 서버에연결요청 clientsocket.connect((servername, serverport)) print("server connected...") rawdata = input('input string: ') # 문자열인코드하여데이터송신 clientsocket.send(rawdata.encode("utf8")) # 데이터수신 modifiedstr = clientsocket.recv(1024) print("from server: ", modifiedstr) 순천향대학교컴퓨터공학과 19 시험주행 순천향대학교컴퓨터공학과 20
TCP 프로그램예동작검토 앞의예제프로그램 서버프로그램에서같은클라이언트연결에대해서도매번연결요청수락 루프내에서연결요청수락 클라이언트한번데이터송수신후종료 데이터수신시동작 데이터수신시데이터를받을때까지프로그램이블록킹 (blocking) 데이터수신까지프로그램이다른동작을못함 개선된프로그램 채팅프로그램 한번연결수락으로클라이언트종료하지않고계속데이터송수신 루프밖에서연결요청수락 데이터수신블록킹문제 데이터수신동작을독자적인프로그램 ( 쓰레드 ) 로실행하여해결 순천향대학교컴퓨터공학과 21 파이썬쓰레드생성및실행 쓰레드라이브러리 : threading 모듈 쓰레드생성 threading.thread(target= 함수이름, args=( 인수, )) 함수 : return Thread target: 실행될함수이름 args: 함수에전달될인수튜플로표시되며인수가없으면생략인수가하나인경우는 ( 인수,) 로표시 Thread 객체를리턴 쓰레드생성예 t = Thread(target=func, args = (10, 20)) 쓰레드실행 Thread.start() 메소드 순천향대학교컴퓨터공학과 22
from threading import * 쓰레드예 # 쓰레드로실행되는함수 def testprint(m, n=5): print("testprint(%d) "%m) for i in range(m,n): print(" %d" %i) # 쓰레드생성및실행 th = Thread(target=testPrint, t t tp t args=(2,)) th.start() print("mainprint i i t ") for i in range(100,106): print(" %d" %i) # 쓰레드생성및실행 th = Thread(target=testPrint, args=(30,35)) th.start() 순천향대학교컴퓨터공학과 23 시험주행 순천향대학교컴퓨터공학과 24
채팅프로그램예 클라이언트와서버가서로문자를주고받는채팅프로그램예 한번연결수락으로클라이언트종료하지않고계속데이터송수신 루프밖에서연결요청수락 데이터수신동작을독자적인프로그램 ( 쓰레드 ) 로실행 한글송수신을위해 UTF16 인코드 / 디코드 문제점 수신문자가바로출력되지않음 저수준및비동기입출력필요 => 파이썬은 asynchat 모듈제공 순천향대학교컴퓨터공학과 25 채팅프로그램예 서버프로그램 ### 채팅서버프로그램 from socket import * from threading import * # 연결요청수락, 연결소켓리턴 connectionsocket, t addr = serversocket.accept() t() print(" 클라이언트연결됨...", addr, " n") # 메시지수신함수 ( 쓰레드 ) def serverrecv(): while True: # 데이터수신하고, 디코드하여출력 clientmsg = connectionsocket.recv(1024) print("**" + clientmsg.decode("utf16")+" n") # 서버네트워크연결초기화 print(" 서버네트워크연결초기화...") # 호스트주소지정 serverport = 7000 # 서버소켓생성 serversocket = socket(af_inet, SOCK_STREAM) # 주소와소켓결합 serversocket.bind(('', serverport)) # 연결요청청취 serversocket.listen(1) 순천향대학교컴퓨터공학과 26 # 쓰레드생성및실행 Thread(target=serverRecv).start() while True: # 송신데이터입력 rawdata = input() # 문자열인코드하여데이터송신 connectionsocket.send(rawdata.encode("utf16")) t t d (" tf16")) connectionsocket.close()
채팅프로그램예 클라이언트프로그램 ### 채팅클라이언트프로그램 from socket import * from threading import * # 서버에연결요청 clientsocket.connect((servername, t t(( serverport)) print(" 서버연결됨... n") # 메시지수신함수 ( 쓰레드 ) def clientrecv(): while True: # 데이터수신하고, 디코드하여출력 servermsg = clientsocket.recv(1024) print("**" +servermsg.decode("utf16")+" n") clientsocket.close() t l # 쓰레드생성및실행 Thread(target=clientRecv).start() while True: # 송신데이터입력 rawdata = input() # 문자열인코드하여데이터송신 clientsocket.send(rawdata.encode("utf16")) t t d (" tf16")) # 클라이언트네트워크연결초기화 print(" 클라이언트네트워크연결초기화...") # 연결할서버주소지정 servername = '127.0.0.1' serverport = 7000 # 클라이언트소켓생성 clientsocket = socket(af_inet, SOCK_STREAM) 순천향대학교컴퓨터공학과 27 clientsocket.close() 시험주행 순천향대학교컴퓨터공학과 28
네트워크그리드예 - 소개 7 장의배열기반그리드를네트워크버전으로개선 클릭한셀의 2차원배열인덱스값을네트워크데이터로송수신 클라이언트, 서버의클릭한그리드값 ( 색 ) 구분빈공간 : 0 ( 흰색 ), 서버 : 1 ( 녹색 ), 클라이언트 : 2 ( 적색 ) 순천향대학교컴퓨터공학과 29 네트워크그리드예 데이터송신 마우스클릭시데이터송신 송신시리스트를바이트형으로변환하여송신 # 서버송신 if event.type == pygame.mousebuttondown: # 그리드값 1( 서버 ) 로지정 grid[row][column]=1 # 서버인덱스를바이트로변환하여송신 serverindex =[row [row, column] indexbytes = bytes(serverindex) connectionsocket.send(indexbytes) 순천향대학교컴퓨터공학과 30 # 클라이언트송신 if event.type == pygame.mousebuttondown: # 그리드값 2( 클라이언트 ) 로지정 grid[row][column]=2 # 클라이언트인덱스를바이트로변환하여송신 clientindex = [row, column] indexbytes = bytes(clientindex) clientsocket.send(indexbytes)
네트워크그리드예 데이터수신 쓰레드함수로구현 수신시바이트데이터를리스트형으로변환후그리드표시 # 서버메시지수신함수 ( 쓰레드 ) def serverrecv(): while True: # 클라이언트의클릭배열인덱스수신후 # 리스트형으로변환 clientindex = list(connectionsocket.recv(1024)) row = clientindex[0] column = clientindex[1] # 그리드값 2( 클라이언트 ) 로지정 grid[row][column] = 2 # 쓰레드생성및실행 Thread(target=serverRecv).start() # 클라이언트메시지수신함수 ( 쓰레드 ) def clientrecv(): while True: # 서버의클릭배열인덱스수신후 # 리스트형으로변환 serverindex = list(clientsocket.recv(1024)) ( row = serverindex[0] column = serverindex[1] # 그리드값 1( 서버 ) 로지정 grid[row][column] = 1 # 쓰레드생성및실행 Thread(target=clientRecv).start() 순천향대학교컴퓨터공학과 31 네트워크그리드예 서버프로그램 ### 그리드서버프로그램 import pygame from socket import * from threading import * black = ( 0, 0, 0) white = ( 255, 255, 255) green = ( 0, 255, 0) red = ( 255, 0, 0) # 그리드크기지정 width=20 height=20 # 그리드셀간여백 margin=5 # 서버메시지수신함수 ( 쓰레드 ) def serverrecv(): while True: # 클라이언트의클릭배열인덱스수신후 # 리스트형으로변환 clientindex = list(connectionsocket.recv(1024)) row = clientindex[0] 순천향대학교 column 컴퓨터공학과 = clientindex[1] 32 # 그리드값 2( 클라이언트 ) 로지정 grid[row][column] = 2 print("receive, Grid Client Index: ",row,column) # 2차원배열생성 #2 차원배열은리스트의리스트, 0: 빈공간, # 1: 서버, 2: 클라이언트 grid=[] for row in range(10): # 행을위한빈배열추가 grid.append([]) for column in range(10): grid[row].append(0) # 열을추가 # 서버네트워크연결초기화 print("server TCP initialize... ") # 호스트주소지정 serverport = 7000 # 서버소켓생성 serversocket = socket(af_inet, SOCK_STREAM) # 주소와소켓결합 serversocket.bind(('', serverport))
# GUI 연결설계기법요청청취 serversocket.listen(1) # 연결요청수락, 연결소켓리턴 connectionsocket, t addr = serversocket.accept() t() print("client connected...", addr) # 쓰레드생성및실행 Thread(target=serverRecv).start() pygame.init() # 윈도우설정 size=[255,255] screen=pygame.display.set_mode(size) pygame.display.set_caption(" 서버그리드 ") done=false clock=pygame pygame.time.clock() while done==false: for event in pygame.event.get(): if event.type == pygame.quit: done=true if event.type == pygame.mousebuttondown: # 마우스클릭위치 pos = pygame.mouse.get_pos() # x,y 스크린좌표를그리드좌표로변환 column=pos[0] // (width+margin) row=pos[1] // (height+margin) # 그리드값 1( 서버 ) 로지정순천향대학교컴퓨터공학과 33 grid[row][column]=1 print("click ",pos,"grid Server Index: ", row,column) # 서버인덱스를바이트로변환하여송신 serverindex = [row, column] indexbytes = bytes(serverindex) connectionsocket.send(indexbytes) print("send, Grid Server Index: ", row,column) # 그리드그리기 screen.fill(black) for row in range(10): for column in range(10): color = white # 서버클릭그리드값색지정 if grid[row][column] == 1: color = green # 클라이언트클릭그리드값색지정 elif grid[row][column] == 2: color = red pygame.draw.rect(screen,color, [(margin+width)*column+margin, (margin+height)*row+margin,width,height]) clock.tick(20) pygame.display.flip() pygame.quit() 네트워크그리드예 클라이언트프로그램 import pygame from socket import * from threading import * black = ( 0, 0, 0) white = ( 255, 255, 255) green = ( 0, 255, 0) red = ( 255, 0, 0) # 그리드크기지정 width=20 height=20 # 그리드셀간여백 margin=5 # 클라이언트메시지수신함수 ( 쓰레드 ) def clientrecv(): while True: # 서버의클릭배열인덱스수신후 # 리스트형으로변환 serverindex = list(clientsocket.recv(1024)) row = serverindex[0] column = serverindex[1] 순천향대학교컴퓨터공학과 34 # 그리드값 1( 서버 ) 로지정 grid[row][column] = 1 print("receive, Grid Server Index: ",row,column) # 2차원배열생성 #2 차원배열은리스트의리스트, 0: 빈공간, # 1: 서버, 2: 클라이언트 grid=[] for row in range(10): # 행을위한빈배열추가 grid.append([]) for column in range(10): grid[row].append(0) # 열을추가 # 클라이언트네트워크연결초기화 print("client TCP initialize... ") # 연결할서버주소지정 servername = '127.0.0.1' serverport = 7000 # 클라이언트소켓생성 clientsocket = socket(af_inet, SOCK_STREAM)
# GUI 서버에설계기법연결요청 print("click ",pos,"grid Server Index: ", clientsocket.connect((servername, serverport)) row,column) print("server connected...") # 클라이언트인덱스를바이트로 # 쓰레드생성및실행 # 변환하여송신 Thread(target=clientRecv).start() pygame.init() # 윈도우설정 size=[255,255] screen=pygame.display.set_mode(size) pygame.display.set_caption(" 클라이언트그리드 ") done=false clock=pygame.time.clock() while done==false: for event in pygame.event.get(): if event.type type == pygame.quit: done=true if event.type == pygame.mousebuttondown: # 마우스클릭위치 pos = pygame.mouse.get_pos() # x,y 스크린좌표를그리드좌표로변환 column=pos[0] // (width+margin) row=pos[1] // (height+margin) ht i # 그리드값 2( 클라이언트 ) 로지정 grid[row][column]=2 순천향대학교컴퓨터공학과 35 clientindex = [row, column] indexbytes = bytes(clientindex) clientsocket.send(indexbytes) print("send, Grid Client Index: ", row,column) # 그리드그리기 screen.fill(black) for row in range(10): for column in range(10): color = white # 서버클릭그리드값색지정 if grid[row][column] == 1: color = green # 클라이언트클릭그리드값색지정 elif grid[row][column] == 2: color = red pygame.draw.rect(screen,color, rect(screen color [(margin+width)*column+margin, (margin+height)*row+margin,width,height]) clock.tick(20) pygame.display.flip() pygame.quit() 시험주행 - 서버 순천향대학교컴퓨터공학과 36
시험주행 - 클라이언트 순천향대학교컴퓨터공학과 37 과제 1. 앞에서소개된프로그램을작성하고실행 2. 앞에서배운내용을사용한임의의프로그램작성 프로그램설명 프로그램소스 실행결과 순천향대학교컴퓨터공학과 38