in reply to UDP Server on Win32

Recycling some code I wrote in 2004 for just this purpose. Implemented on Windows (Tested with Active perl). Hope it helps. And yes, IO::Socket works fine on Win32.
############################################## # UDP Relay # March 2004, by Netwallah # This program can be used as a Client, server, or Relay # for UDP packets. # In CLIENT mode, it sends whatever is keyed in to a Dest UDP IP:Port # In SERVER mode, it receives packets on a port. # In RELAY mode, it receives packets, and forwards them to a different + IP:port. # UDP only. # --How to Run --- # perl UDPRelay <Mode> <Params> # <Mode> is one of C S or R # In Client mode, Params are <Dest IP> and <Dest-port> # In Server mode, Params are a list of ports to listen on # In Relay mode, Params are [<listen-port> <Dest IP> <Dest-port>] ... # # It can relay multiple ports with a single instance. ############################################### use strict; use warnings; use IO::Socket; use IO::Select; my $MAX_TO_READ = 1024; my $ClientServer = shift or die "Please specify CLIENT SERVER or RELAY + mode"; my ($datagram,$flags,$dest_port,$dest_addr,$send_socket, %Conversation); $| = 1; # autoflush STDOUT if ($ClientServer =~m/^c/i){ #----- Client ---------- $dest_addr = shift or die "Dest addr required for Client"; $dest_port = shift or die "dest port required for Client"; # Need ex +tra param $send_socket=Make_Send_Socket($dest_addr,$dest_port); Send_Msgs(); # Send_and_Rcv_Forked(); }elsif ($ClientServer =~m/^s/i){ # Server ------- Rcv_Msgs(\&Msg_Handler,1,\@ARGV); }else{ ## We are a RELAY --- ------------------------ #Relay comes in triplets - ListenPort, DestAddr, DestPort my (@ListenAddrs, @SendSockets);; while (my $listen=shift){ $dest_addr = shift or die "Dest addr required for relay"; $dest_port = shift or die "dest port required for RELAY"; # Need e +xtra param push @SendSockets, # $Relay{$listen}{SENDSOCKET} = $Conversation{$listen}{SERVSOCKET} = Make_Send_Socket($dest_addr,$dest_port); push @ListenAddrs,$listen; $Conversation{$listen}{SERVIP} =$dest_addr; $Conversation{$listen}{SERVPORT} =$dest_port; } Rcv_Msgs(\&Relay_Handler,0,\@ListenAddrs,\@SendSockets); } ########################################### sub Make_Send_Socket { my ($dest_addr,$dest_port) = @_; my $send_socket = IO::Socket::INET->new( PeerPort => $dest_port, PeerAddr => $dest_addr, Proto => "udp") or die "Couldn't be a udp Sender to $dest_addr on port $dest_por +t : $@\n"; return $send_socket; } ################################ sub Send_Msgs{ print "I am the Client - please enter data to send to $dest_addr on + port $dest_port:\n"; $dest_addr or die "Dest IP not specified\n"; while (<>){ chomp; m/quit/i and exit 0; #send SOCKET,MSG,FLAGS,TO length($_) and $send_socket->send ($_); sleep .2; # Wait for response... #if (IO::Select->select ( [$send_socket], undef, undef , 2 )) +{ # check for response print "RCV:" . read_socket($send_socket, $datagram) . "\ +n"; #} } exit; } ####################################### sub Send_and_Rcv_Forked{ # Broken print "I am the Forked Client - please enter data to send to $dest_ +addr on port $dest_port:\n"; $dest_addr or die "Dest IP not specified\n"; defined(my $child = fork) or die "fork() failed: $!"; if ($child == 0){ #Child process while (my $data=read_socket($send_socket, $datagram)){ print "RCV $data\n"; } exit; }else{ print "Parent here ..Child=$child \n"; while (<>){ chomp; m/quit/i and exit 0; #send SOCKET,MSG,FLAGS,TO $send_socket->send ($_); } }; } ####################################### sub Rcv_Msgs{ my $handler_sub = shift; my $Echo_Request = shift; # Does he want us to Echo ? my @PortList = @{shift()} or die "Please specify one or more ports t +o listen on"; my @ExtraHandles = @{shift() || []}; # Existing handles to listen on +. my $Socket_Selector = IO::Select->new(); my @readyHandles; my %SockHandle_To_Port; # Setup all receive sockets and selector foreach my $port (@PortList){ my $handle = IO::Socket::INET->new( LocalPort => $port, Proto => "udp") or die "Couldn't be a udp Listener on port $port : $@\n"; $Socket_Selector->add($handle); $SockHandle_To_Port{$handle} = $port; # Next line required for RELAY operation... $Conversation{$Conversation{$port}{SERVPORT}}{CLIENTSOCKET} = $han +dle; } # Throw in the STDIN ... ## $Socket_Selector->add(\*STDIN); # Does not work on Win32 # We also listen on the extra handles... foreach(@ExtraHandles){ $Socket_Selector->add($_); #Hmm - how do we associate these with what we sent ? } print "I am the SERVER ====Go into a loop receiving messages:\n"; #while (my $Sender_Info = $rcv_socket->recv($datagram, $MAX_TO_READ, + $flags)) { while(@readyHandles = $Socket_Selector->can_read){ foreach my $h (@readyHandles){ # Find Port corresponding to handle.... my $rcvport = $SockHandle_To_Port{$h} || 0; my ( $Sender_addr, $Sender_port, $datagram) = read_socket($ +h); &$handler_sub($Sender_addr, $Sender_port, $datagram,$rcvport +); $Echo_Request and Process_Echo_And_commands($Echo_Request,$h +,$datagram); # ECHO it } } } ############################### sub read_socket{ my $h = shift; # Socket Handle my ($datagram,$flags); my $Sender_Info = $h->recv($datagram, $MAX_TO_READ, $flags) or ret +urn 0; my ($Sender_port, $Sender_iaddr_binary) = sockaddr_in($Sender_Info +); my $Sender_addr = inet_ntoa($Sender_iaddr_binary); return $Sender_addr, $Sender_port, $datagram; } ############################### sub Msg_Handler{ my ($peer_addr, $port, $datagram,$rcvport) = @_; print "Rcv $rcvport from $peer_addr:$port \t:$datagram\n"; } ################################## sub Process_Echo_And_commands{ my ($Options,$sock,$Msg) = @_; $sock->send("ECHO:$Msg"); #Handle any recognized commands.. if ($Msg =~m/^CMD\s+(.+)/){ my $result = `$1`; print "\t$1:$result\n"; $sock->send($result) } } ################################## sub Relay_Handler{ Msg_Handler(@_); # Print it first .. No parsing my ($sender_addr, $Sender_port, $datagram,$rcvport) = @_; #my $output_handle = $Relay{$rcvport}{SENDSOCKET}; my $output_handle = $Conversation{$rcvport}{SERVSOCKET}; if ($rcvport == 0){#This is a response that needs to return to clie +nt.. #Send it to Sender_port's handle #print "--Relaying Server response to orig client for $Sender +_port:$datagram\n"; $output_handle = $Conversation{$Sender_port}{CLIENTSOCKET}; } $output_handle->send($datagram); # Relay it }

     ..to maintain is to slowly feel your soul, sanity and sentience ebb away as you become one with the Evil.

Replies are listed 'Best First'.
Re^2: UDP Server on Win32
by mpapet (Novice) on Mar 10, 2009 at 18:39 UTC
    Under the following conditions,

    1. Win 2003 server

    2. Strawberry Perl (Not activestate's distro)

    3. I do not use the listen parameter.

    then IO::Socket::INET "works."

    If I use the listen parameter, then the code errors out with an "unknown error" message. The code provided in the comments works because the listen parameter is not used.

    Thank you for the code. It works great.