in reply to To Fork for Not to Fork

The problem with your server code is that, once it gets into that while loop, there is another inner while loop to communicate with the first client (Your code looks like it is reading from STDIN, but I think it is a simple typo on your side, as it makes less sense, so i take it as reading from client socket). It simply stuck there as long as the first client is connected. Once the first client is disconnected, the server starts to get empty strings (or undef, platform dependent), and quit the inner while loop. Only then, your execution path goes back to that accept statement.

One way is to make your server multi-threaded. One thread keeps accept connections, when the other one reads from clients by using select to determine readable ones.

Another choice is to spawn thread for each connection.

Third solution. Actually it is even okay to not use multi-thread or fork, simply make sure your server will accept new connections once a while, instead of stuck with one client.

Do a super search with my name as author, and search for key words: Socket and threads. You can find quite a few code samples for different purposes. They are helpful.

Here is a sample to spawn a new thread for each connection:

server: use strict; use IO::Socket; use threads; $|++; my $server = IO::Socket::INET->new(LocalPort => '5123',Reuse => 1,List +en => 5) or die "Could not create server: $!\n"; while (my $client = $server->accept()) { threads->create(\&talk_with_one_client, $client)->detach(); } sub talk_with_one_client { my $client = shift; while (my $line = <$client>) { print $line; chomp $line; print $client $line + 1, "\n"; } } client: use strict; use IO::Socket; $|++; my $socket = IO::Socket::INET->new(PeerAddr => "localhost", PeerPort = +> '5123', Proto => "tcp") or die "Could not create client: $!\n"; print $socket "1\n"; while (my $line = <$socket>) { print $line; chomp $line; sleep 1; print $socket $line + 1, "\n"; }

Replies are listed 'Best First'.
Re: Re: To Fork for Not to Fork
by chromatic (Archbishop) on Nov 10, 2003 at 22:56 UTC

    I downvoted this reply because it doesn't answer the question. (It also demonstrates two useless uses of autoflush, but that's a different problem.)

    The original code has two main problems: child processes don't exit and parent processes block on STDIN. You can certainly possibly avoid these errors by throwing away the example code and rewriting it according to a different concurrency model, but that really doesn't help the original poster learn anything forking.

      The use of $|++ is not useless. I can agree there is no need for it to appear in my client code, but there is a good reason for it to appear in the server code.

      From time to time, I saw posts complaining their codes are not working simply because of the confusion caused by not-flushed debug infos, which can be easily fixed by setting $|. It is a better practice in multi-threading programming ,to turn on autoflush regardless, unless it is forbidden by the nature of your application. Instead of saying it is useless, I see it as a better style.

      I didn't notice the original post is reading from STDIN, instead of the client socket. That's my mistake, but it is understandable, as that doesn't make sense there. I think that's just a simple mistake, and the original author's purpose is to read from the client. However as I pointed out in my original post, his structure is wrong, even changing it to read from client, he will still stuck communicating with the first client, and not going back to accept() until the first client ended.

      BTW, next time there is no need to tell me about the down vote. I may think about the reason for getting down voted, but not interested in knowing who did it. Please keep it for your privacy.

      As for the technical side, I am a strong promoter for threads, and that was where I was getting. I see it much more important to get the direction correct, than anything else.

        For my information, can you explain what you consider good about threads?

        My overall opinion is still pretty much what I said a long time ago at Threads vs Forking (Java vs Perl). Switching threads is faster, debugging multi-threaded programs is much harder, and as the tangential discussion at the end points out, forking scales better if extreme scalability is needed. (The fact that high-end boxes now tend to jump hoops to avoid scheduling different threads on different CPUs underscores the fundamental scalability issue.)

        I have updated some parts of my opinion though. Perl 5.8's threading model makes threading usable in Perl for definitions of usable that include slow and memory bloated.

        Therefore I would personally avoid going multi-threaded unless I was writing code to run on a platform that strongly pushes you that way (Java and Windows both come to mind), or unless I was writing an application where interactive latency was significantly more important than throughput (eg a user-facing desktop program).

        However I haven't done much with threading (the above shows why I tend to choose not to) and I like to update my information from time to time. (And yes, I do regularly wind up changing my opinion as well...) So I wouldn't mind feedback on why you think that threads are the right direction for people to take in more situations.