2011-08-04 3 views
12

파이썬 파일 객체는 옵션 size 인수를 취하는 read 메소드를 가지고 있습니다.이 인수는 기본적으로 반환 할 최대 바이트 수입니다. 예를 들면 :일반 파일과 동일한 읽기 의미를 갖도록 socket.makefile을 가져올 수 있습니까?

fname = "message.txt" 
open(fname, "w").write("Hello World!") 
print open(fname).read() # prints the entire file contents 
print open(fname).read(5) # print "Hello" 
print open(fname).read(99) # prints "Hello World!" 

그래서 우리의 파일보다 적은 99 자, 바로 사용 가능한 모든 데이터와 read(99) 반환에 대한 호출이있다하더라도.

socket.makefile에서 반환 된 파일 개체에 대해이 동작을하고 싶습니다. 그러나 나는 말한다면 :

import socket 
ADDR = ("localhost", 12345) 

listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
listener.bind(ADDR) 
listener.listen(1) 

client = socket.create_connection(ADDR) 
cf = client.makefile("r+b", bufsize=0) 

server, client_addr = listener.accept() 
sf = server.makefile("r+b", bufsize=0) 

sf.write("Hello World!") 
sf.flush() 
print cf.read(99)   # hangs forever 

socket.makefile 문서에 따르면, "옵션 모드와 BUFSIZE 인수가 내장 된 파일() 함수와 같은 방법으로 해석됩니다." 그러나 원래의 파일 예제는 내가 open(fname, "r+b", 0)라고 말할 때도 작동하지만 소켓 의사 파일로 지정된 바이트 수까지 모든 사용 가능한 데이터를 반환하는 방법을 찾을 수는 없습니다. 난 그냥 사용하는 경우

이 완벽하게 잘 작동하는 것 같다 socket.recv :

import socket 
ADDR = ("localhost", 12345) 

listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
listener.bind(ADDR) 
listener.listen(1) 

client = socket.create_connection(ADDR) 
server, client_addr = listener.accept() 

server.sendall("Hello World!") 
print client.recv(99)   # prints "Hello World!" 

그래서 socket.makefile와 함께이 일을 할 수있는 방법이있다, 또는 "고급"이런 종류의 기능은 단순히 사용할 수 없습니다?

편집 :

import socket 
ADDR = ("localhost", 12345) 

listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
listener.bind(ADDR) 
listener.listen(1) 

client = socket.create_connection(ADDR) 
cf = client.makefile("rwb", buffering=0) 

server, client_addr = listener.accept() 
sf = server.makefile("rwb", buffering=0) 

sf.write(b"Hello World!") 
sf.flush() 
print(cf.read(99))   # prints "Hello World!" 

나는이 차이를 알아 내기 위해 아직 소스 코드에 파고하지 않은 : 파이썬 3.2 socket.makefile의 인수 구문을 변경 한 것으로 보인다 불구하고, 제대로 동작하는 것 두 가지 버전이 있지만 힌트 일 수 있습니다.

+0

@BrandonRhodes을 나는이'sock.shutdown (SHUT_WR)' – Mazyod

답변

22

client.read()은 현재 위치에서 EOF으로 읽으려고하지만 소켓의 EOF는 다른 쪽이 연결을 닫을 때만 나타납니다. 반면에 recv은 읽을 수있는 데이터가 있으면 반환하거나 차단 및 시간 제한 설정에 따라 차단할 수 있습니다.

이 하나 비교 :

import socket 
ADDR = ("localhost", 12345) 

listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
listener.bind(ADDR) 
listener.listen(1) 

client = socket.create_connection(ADDR) 
cf = client.makefile("r+b", bufsize=0) 

server, client_addr = listener.accept() 
sf = server.makefile("r+b", bufsize=0) 

sf.write("Hello World!") 
sf.flush() 
sf.close() 
server.close() 
print cf.read(99)   # does not hang 
+1

이 답변이 정확하게 바로 얻을 소켓을 닫는 또 다른 가능한 대안이라고 생각 : 파일의 개념 동등한 EOF는 소켓 close()입니다. 이 대답을 받아 들여야합니다. –

+0

사용 가능한 데이터로만 읽는다면 여전히 정지됩니까? 나는 99 바이트가 들어 오면 그 블록이 멈추게 될 것이라고 추측한다. IO가 99 바이트 나 EOF를 갖기를 기다리고 있기 때문이다. – Kaliber64

관련 문제