【问题标题】:Connection resets with simple Perl script使用简单的 Perl 脚本重置连接
【发布时间】:2009-10-07 20:03:17
【问题描述】:

下面是一个 Perl 脚本,其唯一目的是接收一个 HTTP 请求,并吐出“503 Service Unavailable”和一条短消息。它工作正常,除了在许多情况下,连接重置,这会导致浏览器显示错误消息。这是在 Win32 上。我不知道它有什么问题。

#!/usr/local/bin/perl

use strict;
use IO::Socket::INET;
my $f = join('', <DATA>);

$SIG{CHLD} = 'IGNORE';
my $sock = IO::Socket::INET->new(ReuseAddr => 1, Listen => 512, LocalPort => 80, LocalHost => '0.0.0.0', Proto => 'tcp');
die "Cant't create a listening socket: $@" unless $sock;

while (my $connection = $sock->accept) {
    my $child;
    die "Can't fork: $!" unless defined ($child = fork());
    if ($child == 0) {
        #print "Child $$ running. ";
        $sock->close;
        do_it($connection);
        #print "Child $$ exiting.\n";
        exit 0;
    } else {
        print "Connection from ".$connection->peerhost."\n";
        $connection->close();
    }
}

sub do_it {
    my $socket = shift;
    my $pr = print $socket $f;
    if (!$pr) {
        $socket->close();
        exit(0);
    }
}

__DATA__
HTTP/1.1 503 Service Unavailable
Date: Mon, 12 Mar 2009 19:12:16 GMT
Server: Down
Connection: close
Content-Type: text/html


<html>
<head><title>Down for Maintenance</title></head>
<body>
<h2>Down for Maintenance</h2>
<p>The site is down for maintenance. It will be online again shortly.</p>
</body>
</html>

【问题讨论】:

  • 您要在哪个版本的 Windows 上试用?有多少个同时连接?
  • 当只有我在本地机器上时会发生这种情况,并且我用鼠标快速刷新(这不是那么快......)。操作系统 = XP。

标签: perl tcp reset


【解决方案1】:

fork 在 Win32 上不是被称为损坏吗?

确实,由于您的子进程所做的事情与您的父部分完全不同,您最好使用threads

在回答您在 cmets 中的问题时,只需考虑将所有分叉逻辑 (!!) 替换为

$peer_name = $connection->peerhost();
threads->create( \&do_it, $connection );
say "Got connection from $peer_name";

(例如参见this。) 并且不要担心在服务器线程以外的任何地方关闭连接。

【讨论】:

  • 是否有我可以使用的应用程序来执行此脚本的功能?我将无法在短时间内整理此脚本以使用线程。
  • 这听起来像。我的猜测是父级中的 close() 调用也关闭了子级的描述符,并且它们正在相互竞争。当然,在 Windows 上做 Unix 风格的 fork 永远不会是一个好的选择,即使它可以工作。
  • @Andy Ross:我是这么想的,但我也想知道让两个独立的进程都认为它们打开了相同的描述符的问题。这看起来也是非常未定义的行为。
【解决方案2】:

HTTP::Daemon 有帮助吗?它包含在核心中。

在 Google 上搜索 windows xp sp3 tcp connection limit 的结果也可能是相关的。

【讨论】:

  • 我真的不认为那篇文章指的是 TCP,而是 SMB
  • @Hasturkun 感谢您指出我链接到错误的文章。我还记得一些关于 TCP 连接限制的事情,但我还没有找到这篇文章。
【解决方案3】:

我的模块 HTTP::Server::Brick 在 Windows 上工作,但不幸的是,测试挂在 Strawberry perl 上(它在待办事项列表中),所以您要么需要手动安装,要么只需复制单个 perl 模块并使用 cpan 来安装依赖项。然而,它确实在 Windows 上的 cygwin 下构建/测试良好,当然在 unix 上也是如此。

以下是我使用 HTTP::Server::Brick 实现您的要求的方法,并指出它相当幼稚,并且遇到与您相同的问题,因为线程/进程的数量没有上限。

use strict;
use warnings;

use HTTP::Server::Brick;
use HTTP::Status qw(:constants);

my $server = HTTP::Server::Brick->new( port => 80 );

my $html = join '', <DATA>;

$server->mount( '/' => {
 wildcard => 1,
 handler => sub {
  my ($req, $res) = @_;
  $res->add_content($html);
  return HTTP_SERVICE_UNAVAILABLE;
 },
   });

$server->start;

__DATA__
<html>
<head><title>Down for Maintenance</title></head>
<body>
<h2>Down for Maintenance</h2>
<p>The site is down for maintenance. It will be online again shortly.</p>
</body>
</html>

还有一个关于在已知已损坏的窗口上对 perl fork 的注释的快速说明,它基本上只是使用 perl 线程来模仿 fork() 调用。它不是无缝的,但对于简单的情况,它是一种使用线程的简单方法。

最后一点 - 也许你最好安装 cygwin 加上 apache 或 lighthttpd 包?为所有 url 发送 503 是一个非常短的 apache 配置文件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-19
    • 2014-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-27
    • 2015-09-07
    相关资源
    最近更新 更多