在perl中通过套接字传递文件名
Passing name of file via socket in perl
我有 2 个用 perl 编写的脚本。第一个获取文件并通过套接字将其发送到服务器。服务器是我的第二个脚本——它保存到一个文件中。
服务器将文件保存为指定名称 - 已在代码中修复。在发送文件之前,如何获取发送文件的名称并将其发送到服务器?
我的代码如下:
客户:
my $socket = IO::Socket::INET->new(
PeerAddr => $local_host,
PeerPort => $local_port,
Proto => 'tcp',
)or die "Alert!";
my $bandwidth = 1024*5 ; # 5Kb/s -
open my $fh, '<', "$direc/$my_data"
or die "couldn't open the file";
my $buffer ;
while( sysread($fh, $buffer , $bandwidth) ) {
print $socket $buffer ;
sleep(1) ;
}
print "Data send.End \n" ;
close ($fh) ;
close($socket) ;
我的服务器:
my $my_socket = new IO::Socket::INET(
LocalHost => $local_host,
LocalPort => $local_port,
Proto => 'tcp',
Listen => 5,
Reuse => 1
);
die "Couldn't open my_socket $!n " unless $my_socket;
print "You can send the data now \n";
my $accepter = $my_socket->accept();
my $count=0;
#print "$directory.$save_dir/$my_data";
open my $fh, '>', "$direc/$save_dir/$my_data" #my data is the name, and it's "fixed", how to take it from client?
or die "Couldn't open the file";
while(<$accepter>){
chomp;
last if $count++ ==10;
say $fh $_;
}
print "End \n";
close $fh;
close $my_socket;
让服务器写入客户端指定的文件名存在安全风险。客户端可以告诉服务器覆盖文件,包括服务器本身。
相反,使用 UUID 作为真实文件名。将客户端文件名/真实文件名对存储在别处。
您需要提出一个协议,以便服务器可以区分文件名和内容。我们可以使用现有格式,例如 JSON 或 YAML,但它们需要将整个文件放入内存并对内容进行编码。你可以编一些东西,比如“第一行是文件名”,但我们可以做得更好。
如果你想流式传输,我们可以使用精简的 HTTP 协议。发送 headers 作为 Key: Value
行。空行结束 headers 并开始发送内容。只需付出一点额外的努力,我们就有了一个可扩展的简单协议。
这是使用 UUID::Tiny and also autodie 的服务器的主循环。
# Read Key: Value headers until we see a blank line.
my %headers;
while(my $line = <$accepter>) {
chomp $line;
last if $line eq "";
my($key, $value) = split /\s*:\s*/, $line;
$headers{$key} = $value;
}
# Store the file in a random filename. Do not use the client's filename
# to avoid a host of security issues.
my $filename = create_uuid_as_string(UUID_V4);
open my $fh, ">", "incoming/$filename";
# Read the content and save it to the file.
my $buf;
while( read($accepter, $buf, 1024) ) {
print $fh $buf;
}
say "$headers{Filename} was stored in incoming/$filename";
close $my_socket;
客户端在发送文件内容之前只发送一个文件名header。
open my $fh, '<', $filename;
print $socket "Filename: $filename\n\n";
my $buffer ;
while( sysread($fh, $buffer , $bandwidth) ) {
print $socket $buffer ;
}
我有 2 个用 perl 编写的脚本。第一个获取文件并通过套接字将其发送到服务器。服务器是我的第二个脚本——它保存到一个文件中。 服务器将文件保存为指定名称 - 已在代码中修复。在发送文件之前,如何获取发送文件的名称并将其发送到服务器? 我的代码如下: 客户:
my $socket = IO::Socket::INET->new(
PeerAddr => $local_host,
PeerPort => $local_port,
Proto => 'tcp',
)or die "Alert!";
my $bandwidth = 1024*5 ; # 5Kb/s -
open my $fh, '<', "$direc/$my_data"
or die "couldn't open the file";
my $buffer ;
while( sysread($fh, $buffer , $bandwidth) ) {
print $socket $buffer ;
sleep(1) ;
}
print "Data send.End \n" ;
close ($fh) ;
close($socket) ;
我的服务器:
my $my_socket = new IO::Socket::INET(
LocalHost => $local_host,
LocalPort => $local_port,
Proto => 'tcp',
Listen => 5,
Reuse => 1
);
die "Couldn't open my_socket $!n " unless $my_socket;
print "You can send the data now \n";
my $accepter = $my_socket->accept();
my $count=0;
#print "$directory.$save_dir/$my_data";
open my $fh, '>', "$direc/$save_dir/$my_data" #my data is the name, and it's "fixed", how to take it from client?
or die "Couldn't open the file";
while(<$accepter>){
chomp;
last if $count++ ==10;
say $fh $_;
}
print "End \n";
close $fh;
close $my_socket;
让服务器写入客户端指定的文件名存在安全风险。客户端可以告诉服务器覆盖文件,包括服务器本身。
相反,使用 UUID 作为真实文件名。将客户端文件名/真实文件名对存储在别处。
您需要提出一个协议,以便服务器可以区分文件名和内容。我们可以使用现有格式,例如 JSON 或 YAML,但它们需要将整个文件放入内存并对内容进行编码。你可以编一些东西,比如“第一行是文件名”,但我们可以做得更好。
如果你想流式传输,我们可以使用精简的 HTTP 协议。发送 headers 作为 Key: Value
行。空行结束 headers 并开始发送内容。只需付出一点额外的努力,我们就有了一个可扩展的简单协议。
这是使用 UUID::Tiny and also autodie 的服务器的主循环。
# Read Key: Value headers until we see a blank line.
my %headers;
while(my $line = <$accepter>) {
chomp $line;
last if $line eq "";
my($key, $value) = split /\s*:\s*/, $line;
$headers{$key} = $value;
}
# Store the file in a random filename. Do not use the client's filename
# to avoid a host of security issues.
my $filename = create_uuid_as_string(UUID_V4);
open my $fh, ">", "incoming/$filename";
# Read the content and save it to the file.
my $buf;
while( read($accepter, $buf, 1024) ) {
print $fh $buf;
}
say "$headers{Filename} was stored in incoming/$filename";
close $my_socket;
客户端在发送文件内容之前只发送一个文件名header。
open my $fh, '<', $filename;
print $socket "Filename: $filename\n\n";
my $buffer ;
while( sysread($fh, $buffer , $bandwidth) ) {
print $socket $buffer ;
}