<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>http://www.jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>http://www.jackxiang.com/post//</link>
<title><![CDATA[PHP SOCKET基础]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[WEB2.0]]></category>
<pubDate>Fri, 20 Aug 2010 10:27:25 +0000</pubDate> 
<guid>http://www.jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	PHP使用Berkley的socket库来创建它的连接。socket只不过是一个数据结构。你使用这个socket数据结构去开始一个客户端和服务器 之间的会话。这个服务器是一直在监听准备产生一个新的会话。当一个客户端连接服务器，它就打开服务器正在进行监听的一个端口进行会话。这时，服务器端接受 客户端的连接请求，那么就进行一次循环。现在这个客户端就能够发送信息到服务器，服务器也能发送信息给客户端。<br/>产生一个Socket，你需要三个变量：一个协议、一个socket类型和一个公共协议类型。产生一个socket有三种协议供选择，继续看下面的内容来 获取详细的协议内容。<br/>定义一个公共的协议类型是进行连接一个必不可少的元素。下面的表我们看看有那些公共的协议类型。<br/>表一：协议<br/>名字/常量&nbsp;&nbsp;&nbsp;&nbsp; 描述<br/>AF_INET 这是大多数用来产生socket的协议，使用TCP或UDP来传输，用在IPv4的地址<br/>AF_INET6&nbsp;&nbsp;&nbsp;&nbsp; 与上面类似，不过是来用在IPv6的地址<br/>AF_UNIX 本地协议，使用在Unix和Linux系统上，它很少使用，一般都是当客户端和服务器在同一台机器上的时候使用<br/>表二：Socket类型<br/>名字/常量&nbsp;&nbsp;&nbsp;&nbsp; 描述<br/>SOCK_STREAM 这个协议是按照顺序的、可靠的、数据完整的基于字节流的连接。这是一个使用最多的socket类型，这个socket是使用TCP来进行传输。<br/>SOCK_DGRAM 这个协议是无连接的、固定长度的传输调用。该协议是不可靠的，使用UDP来进行它的连接。<br/>SOCK_SEQPACKET 这个协议是双线路的、可靠的连接，发送固定长度的数据包进行传输。必须把这个包完整的接受才能进行读取。<br/>SOCK_RAW 这个socket类型提供单一的网络访问，这个socket类型使用ICMP公共协议。（ping、traceroute使用该协议）<br/>SOCK_RDM 这个类型是很少使用的，在大部分的操作系统上没有实现，它是提供给数据链路层使用，不保证数据包顺序<br/>表三：公共协议<br/>名字/常量&nbsp;&nbsp;&nbsp;&nbsp; 描述<br/>ICMP 互联网控制消息协议，主要使用在网关和主机上，用来检查网络状况和报告错误信息<br/>UDP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用户数据报文协议，它是一个无连接，不可靠的传输协议<br/>TCP 传输控制协议，这是一个使用最多的可靠的公共协议，它能保证数据包能够到达接受者那儿，如果在传输过程中发生错误，那么它将重新发送出错数据包。<br/>现在你知道了产生一个socket的三个元素，那么我们就在php中使用socket_create()函数来产生一个socket。这个 socket_create()函数需要三个参数：一个协议、一个socket类型、一个公共协议。socket_create()函数运行成功返回一个 包含socket的资源类型，如果没有成功则返回false。<br/>Resourece socket_create(int protocol, int socketType, int commonProtocol);<br/>现在你产生一个socket，然后呢？php提供了几个操纵socket的函数。你能够绑定socket到一个IP，监听一个socket的通信，接受一 个socket；现在我们来看一个例子，了解函数是如何产生、接受和监听一个socket。<br/>&lt;?php<br/>$commonProtocol = getprotobyname(“tcp”);//使用公共协议名字来获取一个协议类型<br/>$socket = socket_create(AF_INET, SOCK_STREAM, $commonProtocol);//产生一个socket并且返回一个socket资源的实例<br/>socket_bind($socket, ‘localhost’, 1337);//绑定socket到本地计算机<br/>socket_listen($socket);//监听所有进来的socket连接<br/>// More socket functionality to come<br/>?&gt;<br/>上面这个例子产生一个你自己的服务器端。例子第一行，<br/>$commonProtocol = getprotobyname(“tcp”);<br/>使用公共协议名字来获取一个协议类型。在这里使用的是TCP公共协议，如果你想使用UDP或者ICMP协议，那么你应该把 getprotobyname()函数的参数改为“udp”或“icmp”。还有一个可选的办法是不使用getprotobyname()函数而是指定 SOL_TCP或SOL_UDP在socket_create()函数中。<br/>$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);<br/>例子的第二行是产生一个socket并且返回一个socket资源的实例。在你有了一个socket资源的实例以后，你就必须把socket绑定到一个 IP地址和某一个端口上。<br/>socket_bind($socket, ‘localhost’, 1337);<br/>在这里你绑定socket到本地计算机（127.0.0.1）和绑定socket到你的1337端口。然后你就需要监听所有进来的socket连接。<br/>socket_listen($socket);<br/>在第四行以后，你就需要了解所有的socket函数和他们的使用。<br/>表四：Socket函数<br/>函数名&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;描述<br/>socket_accept()&nbsp;&nbsp;&nbsp;&nbsp;接受一个Socket连接<br/>socket_bind()&nbsp;&nbsp;&nbsp;&nbsp; 把socket绑定在一个IP地址和端口上<br/>socket_clear_error()&nbsp;&nbsp; 清除socket的错误或者最后的错误代码<br/>socket_close()&nbsp;&nbsp;&nbsp;&nbsp; 关闭一个socket资源<br/>socket_connect()&nbsp;&nbsp;&nbsp;&nbsp;开始一个socket连接<br/>socket_create_listen()&nbsp;&nbsp; 在指定端口打开一个socket监听<br/>socket_create_pair()&nbsp;&nbsp; 产生一对没有区别的socket到一个数组里<br/>socket_create()&nbsp;&nbsp;&nbsp;&nbsp;产生一个socket，相当于产生一个socket的数据结构<br/>socket_get_option()&nbsp;&nbsp;&nbsp;&nbsp;获取socket选项<br/>socket_getpeername()&nbsp;&nbsp; 获取远程类似主机的ip地址<br/>socket_getsockname()&nbsp;&nbsp; 获取本地socket的ip地址<br/>socket_iovec_add()&nbsp;&nbsp;&nbsp;&nbsp;添加一个新的向量到一个分散/聚合的数组<br/>socket_iovec_alloc()&nbsp;&nbsp; 这个函数创建一个能够发送接收读写的iovec数据结构<br/>socket_iovec_delete()&nbsp;&nbsp; 删除一个已经分配的iovec<br/>socket_iovec_fetch()&nbsp;&nbsp; 返回指定的iovec资源的数据<br/>socket_iovec_free()&nbsp;&nbsp;&nbsp;&nbsp;释放一个iovec资源<br/>socket_iovec_set()&nbsp;&nbsp;&nbsp;&nbsp;设置iovec的数据新值<br/>socket_last_error()&nbsp;&nbsp;&nbsp;&nbsp;获取当前socket的最后错误代码<br/>socket_listen()&nbsp;&nbsp;&nbsp;&nbsp; 监听由指定socket的所有连接<br/>socket_read()&nbsp;&nbsp;&nbsp;&nbsp; 读取指定长度的数据<br/>socket_readv()&nbsp;&nbsp;&nbsp;&nbsp; 读取从分散/聚合数组过来的数据<br/>socket_recv()&nbsp;&nbsp;&nbsp;&nbsp; 从socket里结束数据到缓存<br/>socket_recvfrom()&nbsp;&nbsp;&nbsp;&nbsp;接受数据从指定的socket，如果没有指定则默认当前socket<br/>socket_recvmsg()&nbsp;&nbsp;&nbsp;&nbsp;从iovec里接受消息<br/>socket_select()&nbsp;&nbsp;&nbsp;&nbsp; 多路选择<br/>socket_send()&nbsp;&nbsp;&nbsp;&nbsp; 这个函数发送数据到已连接的socket<br/>socket_sendmsg()&nbsp;&nbsp;&nbsp;&nbsp;发送消息到socket<br/>socket_sendto()&nbsp;&nbsp;&nbsp;&nbsp;发送消息到指定地址的socket<br/>socket_set_block()&nbsp;&nbsp;&nbsp;&nbsp;在socket里设置为块模式<br/>socket_set_nonblock()&nbsp;&nbsp; socket里设置为非块模式<br/>socket_set_option()&nbsp;&nbsp;&nbsp;&nbsp;设置socket选项<br/>socket_shutdown()&nbsp;&nbsp;&nbsp;&nbsp;这个函数允许你关闭读、写、或者指定的socket<br/>socket_strerror()&nbsp;&nbsp;&nbsp;&nbsp;返回指定错误号的详细错误<br/>socket_write()&nbsp;&nbsp;&nbsp;&nbsp; 写数据到socket缓存<br/>socket_writev()&nbsp;&nbsp;&nbsp;&nbsp;写数据到分散/聚合数组<br/>以上所有的函数都是PHP中关于socket的，使用这些函数，你必须把你的socket打开，如果你没有打开，请编辑你的php.ini文件，去掉下面 这行前面的注释：<br/>extension=php_sockets.dll<br/>如果你无法去掉注释，那么请使用下面的代码来加载扩展库：<br/>&lt;?php<br/>if(!extension_loaded(‘sockets’)) &#123;<br/>if(strtoupper(substr(PHP_OS, 3)) == “WIN”) &#123;<br/>dl(‘php_sockets.dll’);<br/>&#125;else&#123;<br/>dl(‘sockets.so’);<br/>&#125;<br/>&#125;<br/>?&gt;<br/>如果你不知道你的socket是否打开，那么你可以使用phpinfo()函数来确定socket是否打开。你通过查看phpinfo信息了解 socket是否打开。<br/>◆　产生一个服务器<br/>&lt;?php<br/>$commonProtocol = getprotobyname(“tcp”);<br/>$socket = socket_create(AF_INET, SOCK_STREAM, $commonProtocol);<br/>socket_bind($socket, ‘localhost’, 1337);<br/>socket_listen($socket);<br/>// Accept any incoming connections to the server<br/>$connection = socket_accept($socket);<br/>if($connection)&#123;<br/>socket_write($connection, “You have connected to the socket…nr”);<br/>&#125;<br/>?&gt;<br/>上面的服务器端有三个问题：1. 它不能接受多个连接。2. 它只完成唯一的一个命令。3. 你不能通过Web浏览器连接这个服务器。<br/>这个第一个问题比较容易解决，你可以使用一个应用程序去每次都连接到服务器。但是后面的问题是你需要使用一个Web页面去连接这个服务器，这个比较困难。 你可以让你的服务器接受连接，然后些数据到客户端（如果它一定要写的话），关闭连接并且等待下一个连接。<br/>在上一个代码的基础上再改进，产生下面的代码来做你的新服务器端：<br/>◆　产生一个新的服务器<br/>&lt;?php<br/>// Set up our socket<br/>$commonProtocol = getprotobyname(“tcp”);<br/>$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);<br/>socket_bind($socket, ‘localhost’, 1337); //socket_bind()&nbsp;&nbsp;&nbsp;&nbsp; 把socket绑定在一个IP地址和端口上<br/>socket_listen($socket);<br/>// Initialize the buffer<br/>$buffer = “NO DATA”;<br/>while(true) &#123;<br/>// Accept any connections coming in on this socket<br/>$connection = socket_accept($socket);//socket_accept()&nbsp;&nbsp;&nbsp;&nbsp;接受一个Socket连接<br/>printf(“Socket connectedrn”);<br/>// Check to see if there is anything in the buffer<br/>if($buffer != “”)&#123;<br/>printf(“Something is in the buffer…sending data…rn”);<br/>socket_write($connection, $buffer . “rn”); //socket_write()&nbsp;&nbsp;&nbsp;&nbsp; 写数据到socket缓存<br/>printf(“Wrote to socketrn”);<br/>&#125;else &#123;<br/>printf(“No Data in the bufferrn”);<br/>&#125;<br/>// Get the input<br/>while($data = socket_read($connection, 1024, PHP_NORMAL_READ))&#123;<br/>//socket_read()&nbsp;&nbsp;&nbsp;&nbsp; 读取指定长度的数据<br/>$buffer = $data;<br/>socket_write($connection, “Information Receivedrn”);<br/>printf(“Buffer: ” . $buffer . “rn”);<br/>&#125;<br/>socket_close($connection); //socket_close()&nbsp;&nbsp;&nbsp;&nbsp; 关闭一个socket资源<br/>printf(“Closed the socketrnrn”);<br/>&#125;<br/>?&gt;<br/>这个服务器端要做什么呢？它初始化一个socket并且打开一个缓存收发数据。它等待连接，一旦产生一个连接，它将打印“Socket connected”在服务器端的屏幕上。这个服务器检查缓冲区，如果缓冲区里有数据，它将把数据发送到连接过来的计算机。然后它发送这个数据的接受信 息，一旦它接受了信息，就把信息保存到数据里，并且让连接的计算机知道这些信息，最后关闭连接。当连接关闭后，服务器又开始处理下一次连接。<br/>◆　产生一个客户端<br/>&lt;?php<br/>// Create the socket and connect<br/>$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);<br/>$connection = socket_connect($socket,’localhost’, 1337);<br/>while($buffer = socket_read($socket, 1024, PHP_NORMAL_READ)) &#123;<br/>if($buffer == “NO DATA”) &#123;<br/>echo(“&lt;p&gt;NO DATA&lt;/p&gt;”);<br/>break;<br/>&#125;else&#123;<br/>// Do something with the data in the buffer<br/>echo(“&lt;p&gt;Buffer Data: ” . $buffer . “&lt;/p&gt;”);<br/>&#125;<br/>&#125;<br/>echo(“&lt;p&gt;Writing to Socket&lt;/p&gt;”);<br/>// Write some test data to our socket<br/>if(!socket_write($socket, “SOME DATArn”))&#123;<br/>echo(“&lt;p&gt;Write failed&lt;/p&gt;”);<br/>&#125;<br/>// Read any response from the socket<br/>while($buffer = socket_read($socket, 1024, PHP_NORMAL_READ))&#123;<br/>echo(“&lt;p&gt;Data sent was: SOME DATA&lt;br&gt; Response was:” . $buffer . “&lt;/p&gt;”);<br/>&#125;<br/>echo(“&lt;p&gt;Done Reading from Socket&lt;/p&gt;”);<br/>?&gt;<br/>这个例子的代码演示了客户端连接到服务器。客户端读取数据。如果这是第一时间到达这个循环的首次连接，这个服务器将发送“NO DATA”返回给客户端。如果情况发生了，这个客户端在连接之上。客户端发送它的数据到服务器，数据发送给服务器，客户端等待响应。一旦接受到响应，那么 它将把响应写到屏幕上。
]]>
</description>
</item><item>
<link>http://www.jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] PHP SOCKET基础]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://www.jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>