안 쓰던 블로그

[파이썬] 소켓 프로그래밍-파일 전송, 파일 수신 본문

언어/파이썬

[파이썬] 소켓 프로그래밍-파일 전송, 파일 수신

proqk 2020. 9. 7. 22:17
반응형

이전 글에서 1:1 채팅 프로그램을 만들었다 (foxtrotin.tistory.com/272)

이번에는 소켓으로 파일을 보내는 프로그램을 만들어 본다

기본적인 내용은 1:1 채팅 프로그램 글에 있습니다

 

파일 처리 방법

파일은 결국 바이너리 파일이라 읽고 쓰기 위해서는 인코딩 과정이 필요하다

그래서 파일을 주고 받을 때도 인코딩을 해서 파일에 쓰고 다시 디코딩 해서 읽어야 한다

 

파일 전송 과정-서버 측

1. 클라이언트가 파일을 요청한다. 이 때 파일 이름은 이진 바이트 스트림 데이터 형태로 온다

2. 파일 이름을 일반 문자열로 변환한다

3. open으로 해당 파일을 연다

4. read로 파일을 1024바이트 읽는다

5. 파일이 빈 문자열일 때까지 계속 1024바이트씩 읽고 전송한다(각 라인을 읽어서 리턴해야 하기 때문에 끊어서)

 

파일 수신 과정-클라이언트 측

1. 서버에 파일을 요청한다

2. 서버가 파일을 1024바이트씩 보내기 시작한다

3. 데이터가 없을 때까지 write로 1024바이트씩 써서 원하는 폴더+파일 이름으로 파일을 만든다

 

 

최종 코드

서버

from socket import *
from os.path import exists
import sys

serverSock = socket(AF_INET, SOCK_STREAM)
serverSock.bind(('', 8080))
serverSock.listen(1)

connectionSock, addr = serverSock.accept()

print(str(addr),'에서 접속했습니다')

filename = connectionSock.recv(1024) #클라이언트한테 파일이름(이진 바이트 스트림 형태)을 전달 받는다
print('받은 데이터 : ', filename.decode('utf-8')) #파일 이름을 일반 문자열로 변환한다
data_transferred = 0

if not exists(filename):
    print("no file")
    sys.exit()

print("파일 %s 전송 시작" %filename)
with open(filename, 'rb') as f:
    try:
        data = f.read(1024) #1024바이트 읽는다
        while data: #데이터가 없을 때까지
            data_transferred += connectionSock.send(data) #1024바이트 보내고 크기 저장
            data = f.read(1024) #1024바이트 읽음
    except Exception as ex:
        print(ex)
print("전송완료 %s, 전송량 %d" %(filename, data_transferred))

 

 

클라이언트

from socket import *
import os
import sys

clientSock = socket(AF_INET, SOCK_STREAM)
clientSock.connect(('127.0.0.1', 8080))

print('연결에 성공했습니다.')
filename = input('전송할 파일 이름을 입력하세요: ')
clientSock.sendall(filename.encode('utf-8'))

data = clientSock.recv(1024)
data_transferred = 0

if not data:
    print('파일 %s 가 서버에 존재하지 않음' %filename)
    sys.exit()

nowdir = os.getcwd()
with open(nowdir+"\\"+filename, 'wb') as f: #현재dir에 filename으로 파일을 받는다
    try:
        while data: #데이터가 있을 때까지
            f.write(data) #1024바이트 쓴다
            data_transferred += len(data)
            data = clientSock.recv(1024) #1024바이트를 받아 온다
    except Exception as ex:
        print(ex)
print('파일 %s 받기 완료. 전송량 %d' %(filename, data_transferred))

 

 

결과

클라이언트.py와 서버.py는 다른 디렉터리에 존재한다

서버.py랑 같은 위치에 dog.jpg가 있는 상태

 

존재하지 않는 파일이면 에러를 출력하고 종료한다

 

 

파일이 존재하면 전송한다

전송이 끝나면 클라이언트.py가 있는 디렉터리에도 dog.jpg가 생긴다

반응형
Comments