python cs 구조 로 간단 한 파일 전송 실현
간단 한 파일 의 전송 을 실현 하려 면 우 리 는 반드시 이러한 문 제 를 고려 해 야 한다.
1.c/s 구조 가 무엇 입 니까?
말 그대로 클 라 이언 트 엔 드/서버 구조 입 니 다.다른 사람 은 대답 이 다 를 수 있 지만 한 가 지 는 같 습 니 다.서버 는 하나의 소프트웨어 나 하드웨어 로 하나 이상 의 클 라 이언 트 에 게 필요 한 서 비 스 를 제공 하 는 데 사 용 됩 니 다.서버 에 존재 하 는 유일한 목적 은 고객 의 요 구 를 기다 리 고 이 고객 에 게 서 비 스 를 제공 한 다음 에 다른 요 구 를 기다 리 는 것 입 니 다.
2.클 라 이언 트 와 서버 는 어떻게 통신 합 니까?
사실은 말하자면 인터넷 에서 두 호스트 가 어떻게 통신 해 야 하 는 지 입 니 다.먼저 우 리 는 ip 주소 로 호스트 를 표시 할 수 있 습 니 다.그러면 통신 할 수 있 습 니까?물론 안 됩 니 다.우 리 는 호스트 의 프로 세 스 를 표시 해 야 합 니 다.물론 프로 토 콜 도 없어 서 는 안 되 거나 없어 서 는 안 됩 니 다.udp 메시지 프로 토 콜 입 니까?tcp 데이터 흐름 프로 토 콜 입 니까?이것 은 개인 적 인 요구 에 달 려 있 습 니 다.네트워크 프로 세 스 를 표시 하 는 유일한 인터페이스 로 사용 합 니 다.
이 두 가지 문 제 를 알 고 싶 습 니 다.저 는 이 문제 의 3 분 의 1 이 이미 해결 되 었 다 고 생각 합 니 다.그 다음 에 저 는 tcp 프로 토 콜 을 선택 하여 전송 하 겠 습 니 다.
서버:
socket()함수 로 socket 설명 자 를 정의 합 니 다.
bid()함 수 는 주소 족 중의 특정한 주 소 를 socket 에 부여 합 니 다.쉽게 말 하면 ipv 4/ipv 6 주소+포트 번호 조합 을 socket 에 부여 하 는 것 입 니 다.
listen()함수 가 socket 을 수 동적 인 형식 으로 바 꾸 어 클 라 이언 트 연결 요청 을 기다 리 고 있 습 니 다.
클 라 이언 트 가 메 시 지 를 보 낼 때 accept()함수 로 요청 을 받 아들 이 고 서버 에 클 라 이언 트 의 socket 설명 자 를 되 돌려 줍 니 다.다음 서버 는 받 은 설명 자로 클 라 이언 트 에 게 정 보 를 보 내 고 정 보 를 받 습 니 다.
우리 프로그램 은 파일 전송 을 실현 하 는 것 입 니 다.제 생각 은 ftp 프로그램 이 클 라 이언 트 가 다운로드 파일 을 업로드 하 는 수 요 를 받 아들 이 는 것 과 유사 합 니 다.서버 가 시 작 된 후 감청 포트(내 가 사용 하 는 9500)는 고객 의 연결 을 기다린다.클 라 이언 트 가 세 번 악 수 를 하고 연결 을 만 든 후에 클 라 이언 트 가 명령 을 입력 하여 클 라 이언 트 에 게 요청 을 합 니 다.'ls'명령 을 입력 하면 서버 에서 다운로드 할 수 있 는 파일 을 볼 수 있 고'put'를 입력 할 수 있 습 니 다. 파일 이름 파일 이름'다운로드 파일 을 업로드 할 수 있 습 니 다.파일 을 업로드 할 때 클 라 이언 트 는 로 컬 파일 을 열 어 파일 내용 을 바 이 너 리 방식 으로 읽 고 send()함수 로 파일 내용 을 보 냅 니 다.서버 는 쓰기 방식 으로 파일 을 열 고 클 라 이언 트 업로드 내용 을 파일 에 기록 하여 파일 업 로드 를 실현 합 니 다.다운로드 파일 은 이와 유사 합 니 다.클 라 이언 트 에서'get'을 전송 합 니 다. 파일 이름'명령 은 동시에 쓰기 방식 으로 파일 을 열 고 서버 에서 파일 을 읽 기 방식 으로 열 고 서버 에 보 내 라 는 명령 을 받 았 습 니 다.
tcp 세 번 악수 연결 만 들 기:
클 라 이언 트 가 connect 를 호출 할 때 연결 요청 이 발생 하여 서버 에 SYN J 패 키 지 를 보 냈 습 니 다.이때 connect 는 차단 상태 에 들 어 갑 니 다.서버 가 연결 요청 을 감청 하면 SYN J 패 키 지 를 받 고 accept 함수 로 요청 을 받 아 클 라 이언 트 에 SYN K,ACK J+1 을 보 냅 니 다.이때 accept 는 차단 상태 에 들 어 갑 니 다.클 라 이언 트 가 서버 의 SYN K,ACK J+1 을 받 은 후 이때 connect 가 되 돌아 와 SYN K 를 확인 합 니 다.서버 가 ACK K+1 을 받 았 을 때 accept 가 되 돌아 와 세 번 의 악 수 를 마치 고 연결 이 되 었 습 니 다.
tcp 네 번 손 흔 들 어 연결 끊 기:
어떤 프로 세 스 가 먼저 close 를 호출 하여 연결 을 주동 적 으로 닫 습 니 다.이때 TCP 는 FIN M 을 보 냅 니 다.다른 한쪽 은 FIN M 을 받 은 후 수 동적 으로 닫 고 이 FIN 을 확인 합 니 다.이 수신 도 파일 끝 문자 로 응용 프로 세 스에 전 달 됩 니 다.FIN 의 수신 은 응용 프로 세 스 가 해당 하 는 연결 에서 추가 데 이 터 를 받 지 못 한 다 는 것 을 의미 하기 때 문 입 니 다.한동안 파일 끝 자 를 받 은 응용 프로 세 스 가 close 를 호출 하여 socket 을 닫 습 니 다.이 로 인해 TCP 도 FIN N 을 보 냅 니 다.이 FIN 의 원본 송신 단 TCP 를 받 아서 확인 합 니 다.
서버 코드:
#!/usr/bin/env python
from socket import *
import time
import sys
import os
HOST = 'localhost'
PORT = 9500
BUFIZ = 1024
ADDR = (HOST,PORT)
def recvfile(filename):
print 'starting receive file...'
f = open(filename,'wb')
cliSockfd.send('no problem')
while True:
data = cliSockfd.recv(4096)
if data == 'EOF':
print 'recved file success!'
break
f.write(data)
f.close()
def sendfile(filename):
print 'starting send file...'
cliSockfd.send('no problem')
f = open(filename,'rb')
while True:
data = f.read(4096)
if not data:
break
cliSockfd.send(data)
f.close()
time.sleep(1)
cliSockfd.send('EOF')
print 'send file success!'
def handle1(act,filename):
if act == 'put':
print 'recving msg!'
recvfile(filename)
elif act == 'get':
print 'sending msg!'
sendfile(filename)
else:
print 'error!'
def handle2(act):
if act == 'ls':
path = sys.path[0]
every_file = os.listdir(path)
for filename in every_file:
cliSockfd.send(filename + ' ')
time.sleep(1)
cliSockfd.send('EOF')
print 'all filename has send to client success!'
else:
print 'command error'
sockfd = socket(AF_INET,SOCK_STREAM)
sockfd.bind(ADDR)
sockfd.listen(5)
while True:
print 'waiting for connection...'
cliSockfd,addr = sockfd.accept()
print '...connected from:',addr
while True:
msg = cliSockfd.recv(4096)
if msg == 'close':
print 'client closed'
break
info = msg.split()
if len(info) == 2:
handle1(*info)
elif len(info) == 1:
handle2(*info)
else:
print 'command error!'
break
클 라 이언 트 코드:
#!/usr/bin/env python
import sys
import socket
import time
HOST = 'localhost'
PORT = 9500
BUFSIZ = 1024
ADDR = (HOST,PORT)
cliSockfd = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
def recvfile(filename):
f = open(filename,'wb')
while True:
msg = cliSockfd.recv(4096)
if msg == 'EOF':
print 'recv file success!'
break
f.write(msg)
f.close
def sendfile(filename):
f = open(filename,'rb')
while True:
msg = f.read(4096)
if not msg:
break
cliSockfd.sendall(msg)
f.close()
time.sleep(1)
cliSockfd.sendall('EOF')
print 'send file success'
def confirm(cliSockfd,client_command):
cliSockfd.send(client_command)
msg = cliSockfd.recv(4096)
if msg == 'no problem':
return True
def handle1(act,filename):
if act == 'put':
if confirm(cliSockfd,client_command):
sendfile(filename)
else:
print 'server error1!'
elif act == 'get':
if confirm(cliSockfd,client_command):
recvfile(filename)
else:
print 'server error2!'
else:
print 'command error!'
def handle2(act):
if act == 'ls':
cliSockfd.send('ls')
while True:
msg = cliSockfd.recv(1024)
if msg == 'EOF':
break
print msg
else:
print 'command error'
try:
cliSockfd.connect(ADDR)
print 'connect to ',ADDR
while True:
client_command = raw_input('>>>')
if not client_command:
continue
msg = client_command.split()
if len(msg) == 2:
handle1(*msg)
elif len(msg) == 1 and msg != ['close']:
handle2(*msg)
elif len(msg) == 1 and msg == ['close']:
cliSockfd.send('close')
break
else:
print 'command error'
except socket.error,e:
print 'error:',e
finally:
cliSockfd.close()
캡 처 실행:서버:
클 라 이언 트:
황소 여러분 을 환영 합 니 다.귀중 한 의견 을 많이 제시 하 세 요.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
로마 숫자를 정수로 또는 그 반대로 변환그 중 하나는 로마 숫자를 정수로 변환하는 함수를 만드는 것이었고 두 번째는 그 반대를 수행하는 함수를 만드는 것이었습니다. 문자만 포함합니다'I', 'V', 'X', 'L', 'C', 'D', 'M' ; 문자열이 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.