바로 지금, 루프에서 한 번에 한 문자 씩 읽어서 \0
문자에 도달합니다. 이 작업을 수행하는 더 좋은 방법이 있습니까?데이터 길이가 알려지지 않은 경우 Perl의 소켓에서 데이터를 수신하는 가장 좋은 방법은 무엇입니까?
답변
데이터 길이를 알 수없는 경우 Perl의 소켓에서 데이터를 수신하는 가장 좋은 방법은 무엇입니까?
어떤 언어에서도이 솔루션을 사용할 수 없습니다. 데이터 길이가 얼마나되는지 모르는 경우 소켓에서 소켓을 모두 수신했는지 여부를 알 수 없습니다.
데이터 흐름이 중단되었다는 결정을 내리기 위해 데이터가 들어 오기 시작한 후 "충분히 오래"되었는지를 확인하기 위해 일종의 메트릭을 사용해야합니다. 그러나 그것은 완벽하지 않습니다.
답변은 프로토콜에 따라 다릅니다. 프로토콜이 '\ 0'을 구분자로 사용하기 때문에 올바른 일을하고있는 것입니다. 펄이 당신을 위해 버퍼링을 처리한다는 것을 확신합니다. 그래서 한 번에 한 글자를 읽는 것이 비효율적이지 않습니다.
많은 네트워크 지향 프로토콜은 길이가있는 문자열 앞에옵니다. 이와 같은 프로토콜을 읽으려면 길이 (보통 프로토콜 사양에 따라 1 또는 2 바이트)를 읽은 다음 그 많은 바이트를 문자열로 읽습니다.
PerlIO는 확실히 버퍼링을 처리하므로 1-char 읽기는 * syscall * 오버 헤드가 발생하지 않지만 여전히 Perl op 루프에서 시간을 낭비합니다 (문자열 연결 수는 말할 것도 없습니다 그 코드에 따라 일어날 수 있습니다). 마이크로 최적화는 아니지만'$ /'+'getline' 접근 방식이 훨씬 더 효율적이고 풍부하다. 그래서 성공한다. – hobbs
설정 \x{00}
(\ 0)로 끝나는 라인을 현지화해야하고, 핸들 getline
, 그래서 같은 :
{
local $/ = "\x{00}";
while (my $line = $sock->getline) {
print "$line\n"; # do whatever with your data here
}
}
당신은 ioctl
와 FIONREAD
을 사용할 수 있습니다. 아래 프로그램이 로컬 호스트에 SSH 서버에 연결하고 인사를 대기 :
#! /usr/bin/perl
use warnings;
use strict;
use subs 'FIONREAD';
require "sys/ioctl.ph";
use Socket;
socket my $s, PF_INET, SOCK_STREAM, getprotobyname "tcp"
or die "$0: socket: $!";
connect $s, sockaddr_in 22, inet_aton "localhost"
or die "$0: connect: $!";
my $rin = "";
vec($rin, fileno($s), 1) = 1;
my $nfound = select my$rout=$rin, "", "", undef;
die "$0: select: $!" if $nfound < 0;
if ($nfound) {
my $size = pack "L", 0;
ioctl $s, FIONREAD, $size
or die "$0: ioctl: $!";
print unpack("L", $size), "\n";
sysread $s, my $buf, unpack "L", $size
or die "$0: sysread: $!";
my $length = length $buf;
$buf =~ s/\r/\\r/g;
$buf =~ s/\n/\\n/g;
print "got: [$buf], length=$length\n";
}
샘플 실행 :
$ ./howmuch 39 got: [SSH-2.0-OpenSSH_5.3p1 Debian-3ubuntu4\r\n], length=39
하지만 당신은 아마 아래 코드에서와 IO::Socket::INET
및 IO::Select
모듈을 사용하여 선호하는 것 즉, 구글 회담 :
#! /usr/bin/perl
use warnings;
use strict;
use subs "FIONREAD";
require "sys/ioctl.ph";
use IO::Select;
use IO::Socket::INET;
my $s = IO::Socket::INET->new(PeerAddr => "google.com:80")
or die "$0: can't connect: [email protected]";
my $CRLF = "\015\012";
print $s "HEAD/HTTP/1.0$CRLF$CRLF" or warn "$0: print: $!";
my @ready = IO::Select->new($s)->can_read;
die "$0: umm..." unless $s == $ready[0];
my $size = pack "L", 0;
ioctl $s, FIONREAD, $size
or die "$0: ioctl: $!";
print unpack("L", $size), "\n";
sysread $s, my $buf, unpack "L", $size
or die "$0: sysread: $!";
my $length = length $buf;
$buf =~ s/\r/\\r/g;
$buf =~ s/\n/\\n/g;
print "got: [$buf], length=$length\n";
출력 :
,536,913,632 10573 got: [HTTP/1.0 200 OK\r\nDate: Sun, 18 Jul 2010 12:03:48 GMT\r\nExpires: -1\r\nCache-Control: private, max-age=0\r\nContent-Type: text/html; charset=ISO-8859-1\r\nSet-Cookie: PREF=ID=6742ab80dd810a95:TM=1279454628:LM=1279454628:S=ewNg64020FbnGzHR; expires=Tue, 17-Jul-2012 12:03:48 GMT; path=/; domain=.google.com\r\nSet-Cookie: NID=36=kn2wtTD4UJ3MYYQ5uvA4iAsrS2wcrb_W781pZ1hrVUhUDHrIJTMg_kOgVKhjQnO5SM6MdC_jrRdxFRyXwyyv5N3Xja1ydhVLWWaYqpMHQOmGVi2K5qRWAKwDhCVRd8WS; expires=Mon, 17-Jan-2011 12:03:48 GMT; path=/; domain=.google.com; HttpOnly\r\nServer: gws\r\nX-XSS-Protection: 1; mode=block\r\n\r\n], length=573
사용할 수있는 데이터가 생기 자마자'sysread'가 반환되므로'FIONREAD '큰 사이즈의'sysread'를 호출하면됩니다. –
사용 가능한 무엇이든 데이터를 읽을 sysread
를 사용할 수 있습니다
my $data;
my $max_length = 1000000;
sysread $sock, $data, $max_length;
펄의 read
기능은 사용자가 요청한 바이트, 또는 EOF의 전체 수를 기다립니다.
이것은 libc stdio fread(3)
과 유사합니다.
Perl의 sysread
데이터가 수신되는 즉시 함수가 반환됩니다.
이것은 UNIX read(2)
과 유사합니다.
sysread
은 버퍼링 된 IO를 우회하므로 버퍼 된 read
과 섞어 사용하지 마십시오.
자세한 내용은 perldoc -f read
및 perldoc -f sysread
을 확인하십시오.
이 특정 질문의 경우 가장 먼저 답을 따르고 getline
과 줄 끝이 \0
인 것을 사용하는 것이 더 좋지만 종료 문자가없는 경우 sysread
을 사용할 수 있습니다.
다음은 약간의 예입니다. 웹 페이지를 요청하고받은 첫 번째 데이터 청크를 인쇄합니다.
#!/usr/bin/perl -w
use strict; use warnings;
use IO::Socket;
my $host = $ARGV[0] || 'google.com';
my $port = $ARGV[1] || 80;
my $sock = IO::Socket::INET->new(Proto => 'tcp', PeerAddr => $host, PeerPort => $port)
or die "connect failed: $!";
$sock->autoflush(1);
# use HTTP/1.1, which keeps the socket open by default
$sock->print("GET/HTTP/1.1\r\nHost: $host\r\n\r\n");
my $reply;
my $max_length = 1000000;
# $sock->read($reply, $max_length); # read would hang waiting for 1000000 bytes
my $count = $sock->sysread($reply, $max_length);
if (!defined $count) {
die "read failed: $!";
}
print $reply;
- 1. fortran에서 길이가 알려지지 않은 문자열 반환
- 2. 암호화 방법이 알려지지 않은 경우 데이터를 해독하는 가장 효과적인 방법은 무엇입니까?
- 3. 크기가 알려지지 않은 경우 java에서 char 배열을 사용하는 방법은 무엇입니까?
- 4. 필요한 경우 데이터베이스에서 데이터를 추출하는 가장 좋은 방법은 무엇입니까?
- 5. 트렌드 데이터를 저장하는 가장 좋은 방법은 무엇입니까?
- 6. 템플릿의 데이터를 채우는 가장 좋은 방법은 무엇입니까?
- 7. 데이터를 안전하게 저장하는 가장 좋은 방법은 무엇입니까?
- 8. QMutex가 알려지지 않은 이유는 무엇입니까?
- 9. 데이터를 캐시하는 가장 좋은 방법은
- 10. C#에서 표준 스레드와 소켓에서 동일한 스레드를 수신하는 방법은 무엇입니까?
- 11. .NET 소켓에서 둘 이상의 주소를 수신하는 방법은 무엇입니까?
- 12. 소켓에서 거대한 데이터를 읽고 socketchannel에 쓰는 방법
- 13. 데이터를 파일로 저장하는 가장 좋은 방법은 무엇입니까?
- 14. 플러그인에서 데이터를 마샬링하는 가장 좋은 방법은 무엇입니까?
- 15. 양식 데이터를 인코딩하는 가장 좋은 방법은 무엇입니까?
- 16. 모델에서 데이터를 변경하는 가장 좋은 방법은 무엇입니까?
- 17. 이 데이터를 검색하는 가장 좋은 방법은 무엇입니까?
- 18. 바이너리 데이터를 캐시하는 가장 좋은 방법은 무엇입니까?
- 19. 데이터 소켓을 차단하는 가장 좋은 방법
- 20. 내 데이터를 저장하는 가장 좋은 장소는 무엇입니까?
- 21. 유형 인수가 알려지지 않은 경우 제네릭 유형의 인스턴스 메소드를 호출하는 방법은 무엇입니까?
- 22. BlackBerry에 데이터를 저장하고 (외부에서) 데이터를 읽는 가장 좋은 방법은 무엇입니까?
- 23. 데이터 세트의 벡터 길이가 다른 경우 FFT
- 24. kABPersonAddressCityKey 알려지지 않은 문제
- 25. 길이가 정의되지 않은 이유는 무엇입니까?
- 26. 관리자 패널 - 레이아웃에 "정적"데이터를 표시하는 가장 좋은 방법은 무엇입니까?
- 27. 잘 알려지지 않은 데이터 구조 및 알고리즘은 무엇입니까?
- 28. ICMP 소켓에서 데이터 수신
- 29. 웹 서비스를 사용하고 데이터를 조작하는 가장 좋은 방법은 무엇입니까?
- 30. 큰 데이터를 데이터 그릿에로드하는 가장 좋은 방법
각 메시지가 '\ o'로 끝나면 도움이 될까요? –
* 문자가 데이터 스트림의 일부로 전송 될 수 없다는 것을 알고있는 한 * 데이터 끝 마커처럼 작동합니다.이 경우 데이터 길이를 알 필요가 없습니다. 어떤 경우에는 귀하의 솔루션이 유효합니다. –
@Gal :'\ o'은 무엇입니까? '\ 0'을 의미합니까? – Svante