http://qs321.pair.com?node_id=61136


in reply to RE(4): MP3 server with IO::Socket
in thread MP3 server with IO::Socket

Hi folks, I've been experiencing the same problem that was reported earlier ("it seems to be going very fast"). I'm on Win32 (both NT4 and Win2k) and played around with the script for a while before figuring out a fix. It looks like a:
BINMODE(SONG);
fixes all. I also took out the forking-ness of the server, just to simplify the debug process, but I'm sure that's OK. With the fix in place, the code segment now looks like this:
<text cut> ... #what song are we playing warn( "play song: $song\n"); #open the song, or continue to try another one open (SONG, $song) || next; #### NEW CODE #### binmode (SONG); #### END NEW CODE #### my $read_status = 1; my $print_status = 1; my $chunk; .... <end cut>
I think this fix suggests that somewhere in the MP3's being streamed, read() was encountering what it thought was an EOF, where in fact it was misinterpreting the data. Am I right? (I guessed at binmode, read the cookbook, then understood)

Hope this helps,

Brainiac

Replies are listed 'Best First'.
Re: Re: RE(4): MP3 server with IO::Socket
by perlmonkey (Hermit) on Feb 28, 2001 at 00:08 UTC
    Thanks for the debugging!
    I dont use windows, so I never think about binmode.
    That routine doesnt hurt on unix, so I will add it into
    the server code for all to use.
    -perlmonkey
      Remember how I said I assumed the forking code was fine? Well, I grabbed your latest code posting, and to my surprise, it wouldn't run! After some more debugging (looks like I'm reading more code than I'm writing lately) I think I've found a contention issue (not really sure)...anywho:
      else { #i'm the parent! warn "(Parent) I'm the parent\n"; #who connected? warn "(Parent) Connecton recieved ... ",$connection>peerhost,"\n"; #close the connection, the parent has already passed # it off to a child. warn "(Parent) Closing connection\n"; sleep 3; $connection->close(); }
      Those extra warn statements lead me to believe that the parent was closing the $connection before the child got to call play_songs hence the sleep call. I chose "3" randomly, but it works fine now, and the sleep doesn't affect any of the logic or flow. Brainiac
        Thanks for the feedback. You must be experiencing some Windows wackyness. Here is some of the logic behind the forking. The parent is not *really* closing the client connection as far as the client is concerned. In a normal Unix operation, the fork will create duplicate file descriptors for all open files (includeing sockets). The child has access to the listen socket and the client socket, but also the parent has access to both sockets. The parent and child have independant file descriptors. So if the parent closes its file descriptor, the child still has it open and the client will still remain connected. Both parent and child have to disconnect from the client before the socket is closed. After the fork the parent and child both have valid sockets connecting to the client. Since the parent doesnt not need its end of the client socket it closes it's piece. But the child's copy of the connection is still open since it has not closed its own copy. Similarly the child does not need the listen socket anymore so it closes it's copy of the listen socket, this does not close the parent's listen socket ... so the server keeps listening. Only when the child closes the client socket does the socket actually close.

        Now that was Unix-land. The rumors I have heard are that Windows-land implemented fork using threads, instead of spawning new processes ... so there could be problems with file handles not being duped with the copies being sent to the child. The only thing that I can think of that a sleep 3 would help would be in the unlikely event that in the windows fork implementation the new thread start running right away leaving the 'parent' thread to continue on it's merry way, while the 'child' thread attempts to dup the parents open filehandles in order to mimic the Unix fork. If the 'child' thread does not have time to dup the file handles before the 'parent' thread closes them then you would get the behavior that you describe. I would consider that to be a bug in the windows implementation of Perl then. Perhaps it would fix things if you upgraded your perl to the latest from ActiveState? Just a thought. Other than that I cant think of a thing that would cause what you describe.

        If there is anyone wise in the way of windows-perl, I am interested to hear if there is a firm answer to this problem.
        -perlmonkey