<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Haskell | 酷 壳 - CoolShell</title>
	<atom:link href="https://coolshell.cn/tag/haskell/feed" rel="self" type="application/rss+xml" />
	<link>https://coolshell.cn</link>
	<description>享受编程和技术所带来的快乐 - Coding Your Ambition</description>
	<lastBuildDate>Mon, 28 Dec 2020 08:22:50 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.2</generator>
	<item>
		<title>编程语言汽车</title>
		<link>https://coolshell.cn/articles/1839.html</link>
					<comments>https://coolshell.cn/articles/1839.html#comments</comments>
		
		<dc:creator><![CDATA[陈皓]]></dc:creator>
		<pubDate>Tue, 24 Nov 2009 10:24:22 +0000</pubDate>
				<category><![CDATA[编程语言]]></category>
		<category><![CDATA[轶事趣闻]]></category>
		<category><![CDATA[Basic]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Erlang]]></category>
		<category><![CDATA[Haskell]]></category>
		<category><![CDATA[Lisp]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Ruby]]></category>
		<guid isPermaLink="false">http://coolshell.cn/?p=1839</guid>

					<description><![CDATA[<p>以前酷壳发布过《操作系统航空公司》戏谑了一下如果操作系统是航空公司会怎么样的一种情况。现在，我们来YY一下编程语言，如果编程语言是汽车，又会怎么样？ Ada  ...</p>
<p class="read-more"><a class="btn btn-default" href="https://coolshell.cn/articles/1839.html"> Read More<span class="screen-reader-text">  Read More</span></a></p>
The post <a href="https://coolshell.cn/articles/1839.html">编程语言汽车</a> first appeared on <a href="https://coolshell.cn">酷 壳 - CoolShell</a>.]]></description>
										<content:encoded><![CDATA[<p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-3415450859608158"
     crossorigin="anonymous"></script><strong><img decoding="async" loading="lazy" class="alignright" title="Oscar Mayer Wienermobile" src="https://coolshell.cn/wp-content/uploads/2009/11/oscar-meyer-wienermobile.jpg" alt="Oscar Mayer Wienermobile" width="225" height="167" /></strong>以前酷壳发布过《<a rel="bookmark" href="https://coolshell.cn/articles/1272.html">操作系统航空公司</a>》戏谑了一下如果操作系统是航空公司会怎么样的一种情况。现在，我们来YY一下编程语言，如果编程语言是汽车，又会怎么样？</p>
<li><strong>Ada</strong>   这是一辆坦克。一个很厚重但很丑的坦克，从不会崩溃。如果你告诉别人你正在驾驶Ada，别人会狂笑不已。但是，你会开着一辆跑车去打战吗？[from Amit Dubey]</li>
<li><strong>汇编语言</strong>   只是一个祼露在外的引擎。你不得不自己去造车，并向其提供汽油，但你在驾车时要小心，因为他会像一只从地狱放出来的蝙蝠一样。其实，对于汇编语言，你自己才是车。[From &#8220;Subterfug&#8221; off digg.com:]</li>
<li><strong>Basic</strong>   是一辆很简单的车，对于一些短途的交通比如去一些超市商店，他是很有用的。以前这是一个对初学者很流行的车，然而，近来它蜕变成脚本，而更新的车型被抛光以应对长途旅程，但那也只是新瓶装旧酒。[from Przemyslaw Wrzos]</li>
<li><strong>C</strong>   是一辆赛车，它的速度是令人难以想象的快，可惜的是它每50公里就会损毁一次。</li>
<li><strong>Cobol</strong>   号称是一辆车，但是，没有哪个“有自尊的司机”会承认以前驾驶过它。</li>
<li><strong>C#</strong>   是一个竞争性的家庭旅行车。一旦你开始使用，你就别想再使用别的竞争者的产品了。</li>
<li><strong>C++</strong>   是一个加大马力的C赛车，其有一堆新增的功能，而且，它只会每250公里损毁一次。可是，一旦它有故障，没人会知道故障发生在哪里。</li>
<p><span id="more-1839"></span></p>
<li><strong>Eiffel</strong>   是一个车，其包括了一个法国口音的内建的驾驶讲师。他会帮你很快的识别你的错误，但是你不能和他争，不然，他会凌辱你后毫不迟疑地把你扔到窗外。[From Daniel Prager ]</li>
<li><strong>Erlang</strong>   是一个汽车车队，你想去哪它都会非常合作。你只需要用一只脚就可以开动好几辆车。但是，一旦你学会了如何在它给你设计的地形上驾驶，你就会很难在别的地形上驾驶了。另外，由于你一次驾驶好几辆车，所以，就算是其中几车损毁了也无关紧要。</li>
<li><strong>Forth</strong>   是一辆你通过一些工具可以自己造出来的车。你的这个车不需要像别的车。然后，一辆Forth 车只有倒档。[By &#8220;256byteram&#8221;, on a comment on Digg.com ]</li>
<li><strong>Fortran</strong>   是一个非常漂亮的老爷车。它可以走得很快，但条件是那是一条很直的路，而且路上只有你自己。我们相信，学习去驾驶一辆Fortran车，你就可能去学习别的车型。</li>
<li><strong>Java</strong>   也是一个家用旅行车，很容易驾驶，但不是很快，而且这是一个你无法伤害自己的车。</li>
<li><strong>Haskell</strong>  是一个令人难以想象的超完美设计的相当漂亮的车，有谣言说，这是一辆要可以行驶在极端怪异地形上的车。有一天，你尝试着要去开它，但你发现它并不是顺着路行驶，而是，它把自己和道路都复制了很多份，每一个道路的复制品上都有一辆车，而这些车的位置都比前一个要往前一些。按理来说，我们可以更便捷地驾驶它，但你却对数据不是很懂，所以，你不知道怎么做。<br />
[Monadic 版:]<strong>Haskell</strong>  并不是一个真正的车。这是一个抽象机器，你需要给足你是怎么去驾驶汽车的流程描述。你不得不把这些抽象机器放到某一个真实的机器中，这样它才能真正的行驶。你并不需要知道，那个真实的机器是怎么工作的。而且，我们还可以把多个抽象机器作成一个抽象机器，这样，当你把其放进真实机器中时，你就能去很多地方了。</li>
<li><strong>Lisp</strong>  看上去像一辆车，但你只需要调整，你可把它变成一个飞机或是一个潜水艇。[from Paul Tanimoto:] 首先，这看起来并不像一辆车，但是你会发现还是有人在开他四处走。在你决定去学习驾驶它后，你会意识到这是一辆你可以制造更多的车的车。你告诉你的朋友，但你的朋友们嘲笑你说这个车看起来太怪异了。但就算是这样，你还是始终在你的车库中放着一辆Lisp，并希望有一天你的朋友会开关他到街上。</li>
<li><strong>Mathematica</strong>   是一个设置精良的车，其从Lisp借鉴了很多但却没有得到应得的声望。它可以知道什么才是到达目的地最有效的道路，但是那需要运气。</li>
<li><strong>Matlab</strong>   是一辆设计给新手司机使用的车，它过可用作一些短途用途，而且，适合它的地形也不多，和是那些“数学车”适合的地形差不多。在这种地面上，驾驶它是非常舒服的，但是一旦你离开适合它的地形，就算是一小辆Matlab的车也会变得很难驾驶。而很多专业的司机都拒绝承认这是一辆车。</li>
<li><strong>Ocaml</strong>   是一个很性感的欧洲车。它并不像 <strong>C </strong>一样的快，但他永远不会被损毁。然后，这是法国式的，所有的控制装置都不在正常的位置。</li>
<li><strong>Perl</strong>   本来应该是一个很酷的车，但是它的驾驶员手册相当的难以理解。另外，即使你能搞懂如何驾驶Perl车，你也不能去驾驶别的车。</li>
<li>
<p style="TEXT-ALIGN: left"><strong>PHP</strong>   是一个 Oscar Mayer Wienermobile（见本文文章头上的图片），它是一个很怪异的车，但是还是有很多的人喜欢去驾驶它。 [from &#8220;CosmicJustice&#8221; off of digg.com]</p>
</li>
<li><strong>Prolog</strong>   是一个完全自动化的车：你只要告诉它目的地是什么样的，它就可以带着你去那。[附录 from Paul Graham:] 然而，说明目的地的工作量和你自己开车到那里的工作时是一样的。[另一个版本] <strong>Prolog</strong>   这个车有一个独一无二的GPS装置。它会去为你寻找你要到的目的地，如果到了路的尽头还没有找到，那么，他会回来然后再去试另一条路，直到找到你的目的地为止。</li>
<li><strong>Python</strong>   是一个相当不错的入门者的车。你没有驾照也可以驾驶它。除非，你真的想把它开得很快，或是在很BT的地形上驾驶。有了它，你可能不再需要别的车。</li>
<li><strong>Ruby</strong>   是一个把Perl, Python和Smalltalk三辆车混合起来的一辆拼装车。一个日本的技师找到了Perl, Python和Smalltalk一些碎片并把这些碎片拼成成了一辆车。很多司机认为这个拼装车比其它三个全部加起来都好。而其它一些司机却喃喃道，这个车提供了很多重复的功能，甚至是三重一样的功能，这些重复的功能在不固定的环境下却又有一些细小的不同，这些重复的功能让这个车更难驾驶。有谣言说Ruby这个车要重新设计。</li>
<li><strong>Smalltalk</strong>   只是一个小型车，其原来的目的只是为了让大家学习驾驶。但是，这个车设计的太好了，就算是很有经验的老手也很喜欢驾驶它。它开起来并不是很快，但是你可以把这个车的各个部件全部解开，并且换上你像要的部件，或是组装成你喜欢的样子。你可以给他发一个短信告诉它你要去哪，它会带着你去那，或是告诉你它听不懂你在说什么。很人性化的一辆车。</li>
<li><strong>Visual Basic</strong>   这是一辆驾驭你的车。 [from &#8220;yivkX360&#8221; on digg.com]</li>
<p> </p>
<p>文章：<a href="http://www.cs.caltech.edu/~mvanier/hacking/rants/cars.html" target="_blank">来源</a><!--



<p align="center"><a href= target=_blank><img decoding="async" src=""></a></p>





<p align="center"><img decoding="async" src="https://coolshell.cn/wp-content/uploads/2020/03/coolshell.weixin.jpg"> <img decoding="async" loading="lazy" src="https://coolshell.cn/wp-content/uploads/2020/03/coolshell.mini_.jpg" width="300" height="300"> <br />关注CoolShell微信公众账号和微信小程序</p>

 

--></p>
<div style="margin-top: 15px; font-size: 16px;color: #cc0000;">
<p align="center"><strong>（转载本站文章请注明作者和出处 <a href="https://coolshell.cn/">酷 壳 &#8211; CoolShell</a> ，请勿用于任何商业用途）</strong></p>
</div>

<div class="wp_rp_wrap  wp_rp_vertical_m" id="wp_rp_first"><div class="wp_rp_content"><h3 class="related_post_title">相关文章</h3><ul class="related_post wp_rp"><li ><a href="https://coolshell.cn/articles/1532.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/plugins/wordpress-23-related-posts-plugin/static/thumbs/24.jpg" alt="到处都是Unix的胎记" width="150" height="150" /></a><a href="https://coolshell.cn/articles/1532.html" class="wp_rp_title">到处都是Unix的胎记</a></li><li ><a href="https://coolshell.cn/articles/2529.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/plugins/wordpress-23-related-posts-plugin/static/thumbs/6.jpg" alt="StackOverflow的404错误页" width="150" height="150" /></a><a href="https://coolshell.cn/articles/2529.html" class="wp_rp_title">StackOverflow的404错误页</a></li><li ><a href="https://coolshell.cn/articles/10337.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/plugins/wordpress-23-related-posts-plugin/static/thumbs/24.jpg" alt="数据即代码：元驱动编程" width="150" height="150" /></a><a href="https://coolshell.cn/articles/10337.html" class="wp_rp_title">数据即代码：元驱动编程</a></li><li ><a href="https://coolshell.cn/articles/7886.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2012/07/muxnt-150x150.jpg" alt="代码执行的效率" width="150" height="150" /></a><a href="https://coolshell.cn/articles/7886.html" class="wp_rp_title">代码执行的效率</a></li><li ><a href="https://coolshell.cn/articles/2053.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/plugins/wordpress-23-related-posts-plugin/static/thumbs/20.jpg" alt="最为奇怪的程序语言的特性" width="150" height="150" /></a><a href="https://coolshell.cn/articles/2053.html" class="wp_rp_title">最为奇怪的程序语言的特性</a></li><li ><a href="https://coolshell.cn/articles/1992.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2009/12/language-fanboys-150x150.jpg" alt="程序员眼中的编程语言" width="150" height="150" /></a><a href="https://coolshell.cn/articles/1992.html" class="wp_rp_title">程序员眼中的编程语言</a></li></ul></div></div>The post <a href="https://coolshell.cn/articles/1839.html">编程语言汽车</a> first appeared on <a href="https://coolshell.cn">酷 壳 - CoolShell</a>.]]></content:encoded>
					
					<wfw:commentRss>https://coolshell.cn/articles/1839.html/feed</wfw:commentRss>
			<slash:comments>23</slash:comments>
		
		
			</item>
		<item>
		<title>到处都是Unix的胎记</title>
		<link>https://coolshell.cn/articles/1532.html</link>
					<comments>https://coolshell.cn/articles/1532.html#comments</comments>
		
		<dc:creator><![CDATA[陈皓]]></dc:creator>
		<pubDate>Sun, 11 Oct 2009 10:01:06 +0000</pubDate>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[fork]]></category>
		<category><![CDATA[Haskell]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[socket]]></category>
		<category><![CDATA[Unix]]></category>
		<guid isPermaLink="false">http://coolshell.cn/?p=1532</guid>

					<description><![CDATA[<p>一说起Unix编程，不必多说，最著名的系统调用就是fork，pipe，exec，kill或是socket了（fork(2), execve(2), pipe(2...</p>
<p class="read-more"><a class="btn btn-default" href="https://coolshell.cn/articles/1532.html"> Read More<span class="screen-reader-text">  Read More</span></a></p>
The post <a href="https://coolshell.cn/articles/1532.html">到处都是Unix的胎记</a> first appeared on <a href="https://coolshell.cn">酷 壳 - CoolShell</a>.]]></description>
										<content:encoded><![CDATA[<p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-3415450859608158"
     crossorigin="anonymous"></script>一说起Unix编程，不必多说，最著名的系统调用就是fork，pipe，exec，kill或是socket了（<a href="http://www.kernel.org/doc/man-pages/online/pages/man2/fork.2.html"><code>fork(2)</code></a>, <a href="http://www.kernel.org/doc/man-pages/online/pages/man2/execve.2.html"><code>execve(2)</code></a>, <a href="http://www.kernel.org/doc/man-pages/online/pages/man2/pipe.2.html"><code>pipe(2)</code></a>, <a href="http://www.kernel.org/doc/man-pages/online/pages/man2/socketpair.2.html"><code>socketpair(2)</code></a>, <a href="http://www.kernel.org/doc/man-pages/online/pages/man2/select.2.html"><code>select(2)</code></a>, <a href="http://www.kernel.org/doc/man-pages/online/pages/man2/kill.2.html"><code>kill(2)</code></a>, <a href="http://www.kernel.org/doc/man-pages/online/pages/man2/sigaction.2.html"><code>sigaction(2)</code></a>）这些系统调用都像是Unix编程的胎记或签名一样，表明着它来自于Unix。</p>
<p>下面这篇文章，将向大家展示Unix下最经典的socket的编程例子——使用fork + socket来创建一个TCP/IP的服务程序。这个编程模式很简单，首先是创建Socket，然后把其绑定在某个IP和Port上上侦听连接，接下来的一般做法是使用一个fork创建一个client服务进程再加上一个死循环用于处理和client的交互。这个模式是Unix下最经典的Socket编程例子。</p>
<p>下面，让我们看看用C，Ruby，Python，Perl，PHP和Haskell来实现这一例子，你会发现这些例子中的Unix的胎记。如果你想知道这些例子中的技术细节，那么，向你推荐两本经典书——《Unix高级环境编程》和《Unix网络编程》。</p>
<p><span id="more-1532"></span></p>
<h4>C语言</h4>
<p>我们先来看一下经典的C是怎么实现的。</p>
<pre class="EnlighterJSRAW" data-enlighter-language="c">/**
 * A simple preforking echo server in C.
 *
 * Building:
 *
 * $ gcc -Wall -o echo echo.c
 *
 * Usage:
 *
 * $ ./echo
 *
 *   ~ then in another terminal ... ~
 *
 * $ echo 'Hello, world!' | nc localhost 4242
 *
 */

#include &lt;unistd.h&gt; /* fork, close */
#include &lt;stdlib.h&gt; /* exit */
#include &lt;string.h&gt; /* strlen */
#include &lt;stdio.h&gt; /* perror, fdopen, fgets */
#include &lt;sys/socket.h&gt;
#include &lt;sys/wait.h&gt; /* waitpid */
#include &lt;netdb.h&gt; /* getaddrinfo */

#define die(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)

#define PORT "4242"
#define NUM_CHILDREN 3

#define MAXLEN 1024

int readline(int fd, char *buf, int maxlen); // forward declaration

int
main(int argc, char** argv)
{
    int i, n, sockfd, clientfd;
    int yes = 1; // used in setsockopt(2)
    struct addrinfo *ai;
    struct sockaddr_in *client;
    socklen_t client_t;
    pid_t cpid; // child pid
    char line[MAXLEN];
    char cpid_s[32];
    char welcome[32];

    /* Create a socket and get its file descriptor -- socket(2) */
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
    die("Couldn't create a socket");
    }

    /* Prevents those dreaded "Address already in use" errors */
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&amp;yes, sizeof(int)) == -1) {
    die("Couldn't setsockopt");
    }

    /* Fill the address info struct (host + port) -- getaddrinfo(3) */
    if (getaddrinfo(NULL, PORT, NULL, &amp;ai) != 0) {
    die("Couldn't get address");
    }

    /* Assign address to this socket's fd */
    if (bind(sockfd, ai-&gt;ai_addr, ai-&gt;ai_addrlen) != 0) {
    die("Couldn't bind socket to address");
    }

    /* Free the memory used by our address info struct */
    freeaddrinfo(ai);

    /* Mark this socket as able to accept incoming connections */
    if (listen(sockfd, 10) == -1) {
    die("Couldn't make socket listen");
    }

    /* Fork you some child processes. */
    for (i = 0; i &lt; NUM_CHILDREN; i++) {
    cpid = fork();
    if (cpid == -1) {
        die("Couldn't fork");
    }

    if (cpid == 0) { // We're in the child ...
        for (;;) { // Run forever ...
        /* Necessary initialization for accept(2) */
        client_t = sizeof client;

        /* Blocks! */
        clientfd = accept(sockfd, (struct sockaddr *)&amp;client, &amp;client_t);
        if (clientfd == -1) {
            die("Couldn't accept a connection");
        }

        /* Send a welcome message/prompt */
        bzero(cpid_s, 32);
        bzero(welcome, 32);
        sprintf(cpid_s, "%d", getpid());
        sprintf(welcome, "Child %s echo&gt; ", cpid_s);
        send(clientfd, welcome, strlen(welcome), 0);

        /* Read a line from the client socket ... */
        n = readline(clientfd, line, MAXLEN);
        if (n == -1) {
            die("Couldn't read line from connection");
        }

        /* ... and echo it back */
        send(clientfd, line, n, 0);

        /* Clean up the client socket */
        close(clientfd);
        }
    }
    }

    /* Sit back and wait for all child processes to exit */
    while (waitpid(-1, NULL, 0) &gt; 0);

    /* Close up our socket */
    close(sockfd);

    return 0;
}

/**
 * Simple utility function that reads a line from a file descriptor fd,
 * up to maxlen bytes -- ripped from Unix Network Programming, Stevens.
 */
int
readline(int fd, char *buf, int maxlen)
{
    int n, rc;
    char c;

    for (n = 1; n &lt; maxlen; n++) {
    if ((rc = read(fd, &amp;c, 1)) == 1) {
        *buf++ = c;
        if (c == '\n')
        break;
    } else if (rc == 0) {
        if (n == 1)
        return 0; // EOF, no data read
        else
        break; // EOF, read some data
    } else
        return -1; // error
    }

    *buf = '\0'; // null-terminate
    return n;
}
</pre>
<h4>Ruby</h4>
<p>下面是Ruby，你可以看到其中的fork</p>
<pre class="EnlighterJSRAW" data-enlighter-language="ruby">
# simple preforking echo server in Ruby
require 'socket'

# Create a socket, bind it to localhost:4242, and start listening.
# Runs once in the parent; all forked children inherit the socket's
# file descriptor.
acceptor = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
address = Socket.pack_sockaddr_in(4242, 'localhost')
acceptor.bind(address)
acceptor.listen(10)

# Close the socket when we exit the parent or any child process. This
# only closes the file descriptor in the calling process, it does not
# take the socket out of the listening state (until the last fd is
# closed).
#
# The trap is guaranteed to happen, and guaranteed to happen only
# once, right before the process exits for any reason (unless
# it's terminated with a SIGKILL).
trap('EXIT') { acceptor.close }

# Fork you some child processes. In the parent, the call to fork
# returns immediately with the pid of the child process; fork never
# returns in the child because we exit at the end of the block.
3.times do
  fork do
    # now we're in the child process; trap (Ctrl-C) interrupts and
    # exit immediately instead of dumping stack to stderr.
    trap('INT') { exit }

    puts "child #$$ accepting on shared socket (localhost:4242)"
    loop {
      # This is where the magic happens. accept(2) blocks until a
      # new connection is ready to be dequeued.
      socket, addr = acceptor.accept
      socket.write "child #$$ echo&gt; "
      socket.flush
      message = socket.gets
      socket.write message
      socket.close
      puts "child #$$ echo'd: '#{message.strip}'"
    }
    exit
  end
end

# Trap (Ctrl-C) interrupts, write a note, and exit immediately
# in parent. This trap is not inherited by the forks because it
# runs after forking has commenced.
trap('INT') { puts "\nbailing" ; exit }

# Sit back and wait for all child processes to exit.
Process.waitall

</pre>
<h4>Python</h4>
<pre class="EnlighterJSRAW" data-enlighter-language="python">"""
Simple preforking echo server in Python.
"""

import os
import sys
import socket

# Create a socket, bind it to localhost:4242, and start
# listening. Runs once in the parent; all forked children
# inherit the socket's file descriptor.
acceptor = socket.socket()
acceptor.bind(('localhost', 4242))
acceptor.listen(10)

# Ryan's Ruby code here traps EXIT and closes the socket. This
# isn't required in Python; the socket will be closed when the
# socket object gets garbage collected.

# Fork you some child processes. In the parent, the call to
# fork returns immediately with the pid of the child process;
# fork never returns in the child because we exit at the end
# of the block.
for i in range(3):
    pid = os.fork()

    # os.fork() returns 0 in the child process and the child's
    # process id in the parent. So if pid == 0 then we're in
    # the child process.
    if pid == 0:
        # now we're in the child process; trap (Ctrl-C)
        # interrupts by catching KeyboardInterrupt) and exit
        # immediately instead of dumping stack to stderr.
        childpid = os.getpid()
        print "Child %s listening on localhost:4242" % childpid
        try:
            while 1:
                # This is where the magic happens. accept(2)
                # blocks until a new connection is ready to be
                # dequeued.
                conn, addr = acceptor.accept()

                # For easier use, turn the socket connection
                # into a file-like object.
                flo = conn.makefile()
                flo.write('Child %s echo&gt; ' % childpid)
                flo.flush()
                message = flo.readline()
                flo.write(message)
                flo.close()
                conn.close()
                print "Child %s echo'd: %r" % \
                          (childpid, message.strip())
        except KeyboardInterrupt:
            sys.exit()

# Sit back and wait for all child processes to exit.
#
# Trap interrupts, write a note, and exit immediately in
# parent. This trap is not inherited by the forks because it
# runs after forking has commenced.
try:
    os.waitpid(-1, 0)
except KeyboardInterrupt:
    print "\nbailing"
    sys.exit()
</pre>
<h4>Perl</h4>
<pre class="EnlighterJSRAW" data-enlighter-language="perl">#!/usr/bin/perl
use 5.010;
use strict;

# simple preforking echo server in Perl
use Proc::Fork;
use IO::Socket::INET;

sub strip { s/\A\s+//, s/\s+\z// for my @r = @_; @r }

# Create a socket, bind it to localhost:4242, and start listening.
# Runs once in the parent; all forked children inherit the socket's
# file descriptor.
my $acceptor = IO::Socket::INET-&gt;new(
    LocalPort =&gt; 4242,
    Reuse     =&gt; 1,
    Listen    =&gt; 10,
) or die "Couln't start server: $!\n";

# Close the socket when we exit the parent or any child process. This
# only closes the file descriptor in the calling process, it does not
# take the socket out of the listening state (until the last fd is
# closed).
END { $acceptor-&gt;close }

# Fork you some child processes. The code after the run_fork block runs
# in all process, but because the child block ends in an exit call, only
# the parent executes the rest of the program. If a parent block were
# specified here, it would be invoked in the parent only, and passed the
# PID of the child process.
for ( 1 .. 3 ) {
    run_fork { child {
        while (1) {
            my $socket = $acceptor-&gt;accept;
            $socket-&gt;printflush( "child $$ echo&gt; " );
            my $message = $socket-&gt;getline;
            $socket-&gt;print( $message );
            $socket-&gt;close;
            say "child $$ echo'd: '${\strip $message}'";
        }
        exit;
    } }
}

# Trap (Ctrl-C) interrupts, write a note, and exit immediately
# in parent. This trap is not inherited by the forks because it
# runs after forking has commenced.
$SIG{ 'INT' } = sub { print "bailing\n"; exit };

# Sit back and wait for all child processes to exit.
1 while 0 &lt; waitpid -1, 0;
</pre>
<h4>PHP</h4>
<pre class="EnlighterJSRAW" data-enlighter-language="perl">
&lt;?
/*
Simple preforking echo server in PHP.
Russell Beattie (russellbeattie.com)
*/

/* Allow the script to hang around waiting for connections. */
set_time_limit(0);

# Create a socket, bind it to localhost:4242, and start
# listening. Runs once in the parent; all forked children
# inherit the socket's file descriptor.
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket,'localhost', 4242);
socket_listen($socket, 10);

pcntl_signal(SIGTERM, 'shutdown');
pcntl_signal(SIGINT, 'shutdown');

function shutdown($signal){
    global $socket;
    socket_close($socket);
    exit();
}
# Fork you some child processes. In the parent, the call to
# fork returns immediately with the pid of the child process;
# fork never returns in the child because we exit at the end
# of the block.
for($x = 1; $x &lt;= 3; $x++){
   
    $pid = pcntl_fork();
   
    # pcntl_fork() returns 0 in the child process and the child's
    # process id in the parent. So if $pid == 0 then we're in
    # the child process.
    if($pid == 0){

        $childpid = posix_getpid();
       
        echo "Child $childpid listening on localhost:4242 \n";

        while(true){
            # This is where the magic happens. accept(2)
            # blocks until a new connection is ready to be
            # dequeued.
            $conn = socket_accept($socket);

            $message = socket_read($conn,1000,PHP_NORMAL_READ);
           
            socket_write($conn, "Child $childpid echo&gt; $message");
       
            socket_close($conn);
       
            echo "Child $childpid echo'd: $message \n";
       
        }

    }
}
#
# Trap interrupts, write a note, and exit immediately in
# parent. This trap is not inherited by the forks because it
# runs after forking has commenced.
try{

    pcntl_waitpid(-1, $status);

} catch (Exception $e) {

    echo "bailing \n";
    exit();

}</pre>
<h4>Haskell</h4>
<pre class="EnlighterJSRAW" data-enlighter-language="haskell">import Network
import Prelude hiding ((-))
import Control.Monad
import System.IO
import Control.Applicative
import System.Posix
import System.Exit
import System.Posix.Signals

main :: IO ()
main = with =&lt;&lt; (listenOn - PortNumber 4242) where

  with socket = do
    replicateM 3 - forkProcess work
    wait

    where
    work = do
      installHandler sigINT (Catch trap_int) Nothing
      pid &lt;- show &lt;$&gt; getProcessID
      puts - "child " ++ pid ++ " accepting on shared socket (localhost:4242)"
     
      forever - do
        (h, _, _) &lt;- accept socket

        let write   = hPutStr h
            flush   = hFlush h
            getline = hGetLine h
            close   = hClose h

        write - "child " ++ pid ++ " echo&gt; "
        flush
        message &lt;- getline
        write - message ++ "\n"
        puts - "child " ++ pid ++ " echo'd: '" ++ message ++ "'"
        close

    wait = forever - do
      ( const () &lt;$&gt; getAnyProcessStatus True True  ) <code data-enlighter-language="raw" class="EnlighterJSRAW">catch</code> const trap_exit

    trap_int = exitImmediately ExitSuccess

    trap_exit = do
      puts "\nbailing"
      sClose socket
      exitSuccess

    puts = putStrLn

  (-) = ($)
  infixr 0 -

</pre>
<p>如果你知道更多的，请你告诉我们。（全文完）<!--



<p align="center"><a href= target=_blank><img decoding="async" src=""></a></p>





<p align="center"><img decoding="async" src="https://coolshell.cn/wp-content/uploads/2020/03/coolshell.weixin.jpg"> <img decoding="async" loading="lazy" src="https://coolshell.cn/wp-content/uploads/2020/03/coolshell.mini_.jpg" width="300" height="300"> <br />关注CoolShell微信公众账号和微信小程序</p>

 

--></p>
<div style="margin-top: 15px; font-size: 16px;color: #cc0000;">
<p align="center"><strong>（转载本站文章请注明作者和出处 <a href="https://coolshell.cn/">酷 壳 &#8211; CoolShell</a> ，请勿用于任何商业用途）</strong></p>
</div>

<div class="wp_rp_wrap  wp_rp_vertical_m" ><div class="wp_rp_content"><h3 class="related_post_title">相关文章</h3><ul class="related_post wp_rp"><li ><a href="https://coolshell.cn/articles/1839.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2009/11/oscar-meyer-wienermobile-150x150.jpg" alt="编程语言汽车" width="150" height="150" /></a><a href="https://coolshell.cn/articles/1839.html" class="wp_rp_title">编程语言汽车</a></li><li ><a href="https://coolshell.cn/articles/2529.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/plugins/wordpress-23-related-posts-plugin/static/thumbs/6.jpg" alt="StackOverflow的404错误页" width="150" height="150" /></a><a href="https://coolshell.cn/articles/2529.html" class="wp_rp_title">StackOverflow的404错误页</a></li><li ><a href="https://coolshell.cn/articles/18360.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2018/05/300x262-150x150.jpg" alt="程序员练级攻略（2018)  与我的专栏" width="150" height="150" /></a><a href="https://coolshell.cn/articles/18360.html" class="wp_rp_title">程序员练级攻略（2018)  与我的专栏</a></li><li ><a href="https://coolshell.cn/articles/7965.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2012/07/fork01jpg-150x150.jpg" alt="一个fork的面试题" width="150" height="150" /></a><a href="https://coolshell.cn/articles/7965.html" class="wp_rp_title">一个fork的面试题</a></li><li ><a href="https://coolshell.cn/articles/7886.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2012/07/muxnt-150x150.jpg" alt="代码执行的效率" width="150" height="150" /></a><a href="https://coolshell.cn/articles/7886.html" class="wp_rp_title">代码执行的效率</a></li><li ><a href="https://coolshell.cn/articles/2053.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/plugins/wordpress-23-related-posts-plugin/static/thumbs/20.jpg" alt="最为奇怪的程序语言的特性" width="150" height="150" /></a><a href="https://coolshell.cn/articles/2053.html" class="wp_rp_title">最为奇怪的程序语言的特性</a></li></ul></div></div>The post <a href="https://coolshell.cn/articles/1532.html">到处都是Unix的胎记</a> first appeared on <a href="https://coolshell.cn">酷 壳 - CoolShell</a>.]]></content:encoded>
					
					<wfw:commentRss>https://coolshell.cn/articles/1532.html/feed</wfw:commentRss>
			<slash:comments>19</slash:comments>
		
		
			</item>
	</channel>
</rss>
