perl套接字客户端/服务器对数据包进行排队
我正在研究车辆跟踪系统,其中GPS设备(socket客户端已编程)与socket服务器通信,以发送GPS坐标等。socket服务器解析数据,并通过get方法发送到http web服务进行进一步处理。我尝试在本地模拟50个客户端,以研究套接字服务器的行为。不幸的是,我看到在解析/获取数据时出现了延迟,即使所有客户端都是在同一时间/不同时间启动的。但我的要求是先到先得,但在这种情况下,情况似乎并非如此。这是否需要处理perl套接字客户端/服务器对数据包进行排队,perl,sockets,tcp,client-server,cpan,Perl,Sockets,Tcp,Client Server,Cpan,我正在研究车辆跟踪系统,其中GPS设备(socket客户端已编程)与socket服务器通信,以发送GPS坐标等。socket服务器解析数据,并通过get方法发送到http web服务进行进一步处理。我尝试在本地模拟50个客户端,以研究套接字服务器的行为。不幸的是,我看到在解析/获取数据时出现了延迟,即使所有客户端都是在同一时间/不同时间启动的。但我的要求是先到先得,但在这种情况下,情况似乎并非如此。这是否需要处理newio::Socket::INET()中的Timeout参数?下面是我的套接字服
newio::Socket::INET()中的Timeout
参数代码>?下面是我的套接字服务器,正在侦听端口11050
#!/usr/bin/perl
use IO::Socket::INET;
$| = 1;
my ($socket,$client_socket);
my ($peeraddress,$peerport);
my $LOGFILE="/home/nuthan/program/input.log";
open (LOG,">>$LOGFILE");
$socket = new IO::Socket::INET ( LocalHost => '192.168.1.110',
LocalPort => '11050', Proto => 'tcp',
Listen => 500, Reuse => 1,
Blocking => 0, Timeout => 2 )
or die "ERROR in Socket Creation : $!\n";
while(1) {
# waiting for new client connection.
$client_socket = $socket->accept();
#print "SOCKET $client_socket SOCKET\n";
if (! $client_socket){
next;
}
# Received from Client :
#356823033046306##0#0000#AUT#1#V#07734.7000,E,1259.5355,N,000.00,288#211011#085017##
#EMI's code(15 numbers)#username#status#password#data type#data volume#base station information#longitude, E,latitude, N, speed, direction#date#time##
$client_socket->recv($data,1500);
print "Received from Client : $data\n";
#print LOG "Received from Client : $data\n";
my ($blah,$EMI,$username,$status,$password,$data_type,$data_volume,
$base_station_info,$dir,$date,$time,$blah1)=split(/\#/,$data);
new_do_get($EMI,$dir,$date,$time);
}
sub new_do_get(){
print "In new_do_get\n";
my ($EMI,$dir,$date,$time) = @_;
my ($longitude,$e,$latitude,$n,$speed,$direction)=split(/,/,$dir);
my $url = "http://192.168.1.110:8080/prototype/socket/location.php?"
. "ln=$longitude<=$latitude&imei=$EMI&d=$date&o=0&v=$speed&t=$time";
# print "$url\n";
use LWP::Simple;
my $content = get $url;
die "Couldn't get $url" unless defined $content;
}
$socket->close();
close LOG;
多线程套接字服务器
环顾四周,意识到,有了如此庞大的客户机,多线程perl套接字就足以解决这个问题了。希望这能帮助别人。
!
#/usr/bin/perl-Tw
严格使用;
开始{$ENV{PATH}='/usr/ucb:/bin'}
使用插座;
使用鲤鱼;
我的$EOL=“\015\012”;
子繁殖远期申报
子日志msg{print“$0$$:@uuAt”,scalar localtime,“\n”}
我的$port=shift | | 11051;
my$proto=getprotobyname('tcp');
($port)=$port=~/^(\d+)$/或死为“无效端口”;
socket(服务器,PF_INET,SOCK_STREAM,$proto)| | die“socket:$!”;
setsockopt(服务器、SOL_套接字、SO_REUSEADDR、,
包装(“l”,1))| |模具“setsockopt:$!”;
绑定(服务器,sockaddr_in($port,INADDR_ANY))| | die“绑定:$!”;
监听(服务器,SOMAXCONN)| |死“监听:$!”;
logmsg“服务器已在端口$port上启动”;
my$waitedpid=0;
我的$paddr;
使用POSIX“:sys_wait_h”;
副收割器{
我的孩子;
而($waitedpid=waitpid(-1,WNOHANG))>0){
logmsg“reaped$waitedpid”。($??“带出口$?”:“”);
}
$SIG{CHLD}=\&REAPER;#厌恶系统
}
$SIG{CHLD}=\&REAPER;
对于($waitedpid=0;
($paddr=accept(客户端、服务器))| |$waitedpid;
$waitedpid=0,关闭客户端)
{
读取(客户端,$buffer,1000);
接下来,如果$waitedpid而不是$paddr;
my($port,$iaddr)=sockaddr_in($paddr);
my$name=gethostbyaddr($iaddr,AF_INET);
logmsg“来自$name[”,的连接,
inet_ntoa($iaddr),“]
$buffer
#您的数据在$buffer中
在港口$port”;
繁殖子{
$|=1;
打印“你好,$name,现在是”,标量localtime,$EOL;
或者承认“不能执行财富:$!”;
};
}
子繁殖{
my$coderef=shift;
除非(@==0&&$coderef&&ref($coderef)等式'CODE'){
坦白“用法:生成代码引用”;
}
我的$pid;
如果(!已定义($pid=fork)){
logmsg“无法分叉:$!”;
返回;
}elsif(pid美元){
logmsg“begat$pid”;
return;#我是家长
}
#否则我就是孩子——去产卵吧
打开(标准输入“&STDOUT”)| |骰子“无法将标准输出复制到标准输出”;
退出&$coderef();
}
对于您声称的效果,您测量的代码太多了。去掉HTTP请求部分,这样您就独立于PHP侦听器和其间的网络。输入一些带有时间戳的逐行日志。-当我猜测50个客户端模拟伪造了GPS设备时,我是正确的吗?如果是,也发布代码。您是否意识到,如果一个客户端决定坐在那里打开套接字,不发送任何内容,那么您的服务器将坐在那里等待它,而忽略所有其他客户端?您需要为每个客户机提供服务,或者使用选择。而不是做后者,想想THNX@德伯特,我意识到它在等待很长时间。环顾四周后,我才知道有这么多的客户端,多线程perl套接字就足以解决这个问题了。我已经在下面发布了代码。现在,我不确定在哪里读取/接收数据。@nuthan:您可以在传递给spawn的匿名子例程中执行此操作。您根本不应该在父进程中这样做。为什么不使用POE?
#!/usr/bin/perl -Tw
use strict;
BEGIN { $ENV{PATH} = '/usr/ucb:/bin' }
use Socket;
use Carp;
my $EOL = "\015\012";
sub spawn; # forward declaration
sub logmsg { print "$0 $$: @_ at ", scalar localtime, "\n" }
my $port = shift || 11051;
my $proto = getprotobyname('tcp');
($port) = $port =~ /^(\d+)$/ or die "invalid port";
socket(Server, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
setsockopt(Server, SOL_SOCKET, SO_REUSEADDR,
pack("l", 1)) || die "setsockopt: $!";
bind(Server, sockaddr_in($port, INADDR_ANY)) || die "bind: $!";
listen(Server,SOMAXCONN) || die "listen: $!";
logmsg "server started on port $port";
my $waitedpid = 0;
my $paddr;
use POSIX ":sys_wait_h";
sub REAPER {
my $child;
while (($waitedpid = waitpid(-1,WNOHANG)) > 0) {
logmsg "reaped $waitedpid" . ($? ? " with exit $?" : '');
}
$SIG{CHLD} = \&REAPER; # loathe sysV
}
$SIG{CHLD} = \&REAPER;
for ( $waitedpid = 0;
($paddr = accept(Client,Server)) || $waitedpid;
$waitedpid = 0, close Client)
{
read(Client, $buffer, 1000);
next if $waitedpid and not $paddr;
my($port,$iaddr) = sockaddr_in($paddr);
my $name = gethostbyaddr($iaddr,AF_INET);
logmsg "connection from $name [",
inet_ntoa($iaddr), "]
$buffer
#your data in $buffer
at port $port";
spawn sub {
$|=1;
print "Hello there, $name, it's now ", scalar localtime, $EOL;
or confess "can't exec fortune: $!";
};
}
sub spawn {
my $coderef = shift;
unless (@_ == 0 && $coderef && ref($coderef) eq 'CODE') {
confess "usage: spawn CODEREF";
}
my $pid;
if (!defined($pid = fork)) {
logmsg "cannot fork: $!";
return;
} elsif ($pid) {
logmsg "begat $pid";
return; # I'm the parent
}
# else I'm the child -- go spawn
open(STDIN, "<&Client") || die "can't dup client to stdin";
open(STDOUT, ">&Client") || die "can't dup client to stdout";
## open(STDERR, ">&STDOUT") || die "can't dup stdout to stderr";
exit &$coderef();
}