当我们是应用多用户程序时,有很多种方法来接收和发送数据。你可以是用基于XML的方法。另一种方法是创建一个定时更新的接收程序。

Socket 可以用来发送数据,它不需要通过计时器来定时检查更新,它仅仅会在有数据更新时才更新。当然socke的作用不仅仅是可以用来发送简单的数据;你甚至可以创建一个多用户的绘画程序,当不同的用户登录发送不同的且与之相对应的数据。

 

理解sockets

Socket 是一个信息的终端(endpoint)或者是通过相同的协议 使一台电脑的部分网络连接到另一台电脑上。与传统的网络连接不同的是 socket可以使两台连接的电脑“交流”的更通畅。

当在internet上请求访问一个站点时,你会得到你请求的页面,但是internet不能主动的将新的数据直接发送给你(客户端),必须要你再次请求才可以(译者http协议的特点)。Socket的出现可以弥补这一缺陷,它可以让server主动给客户端发送更新数据。这一技术被广泛的应用在直接连接程序(direct connection application),例如 即时通讯应用,网络视频应用和团队协作式工作环境。

 

Socket 的安全

Socket需要在电脑间建立直接的链接,所以安全问题是一个值得关注的问题,

一般来说,客户端和服务端都会有自己的安全的方案。例如 flash中的socket建立需要双方都通过彼此的“信任”后才可以建立链接。相对而言,标准协议对通过命令行建立的一般链接是没有任何安全限制的。

 

Socket的服务端

Socket服务端可以用很多种语言来实现,

例如:一个持续运行或者是一个企业级的socket,你肯定是希望每个用户都能连接到你而且限制链接对服务端的危险性也就是安全性。

 

理解socket连接

 

Socket的一部分

一个socket连接是由两部分组成的。第一部分是由服务端,第二部分是由客户端连接到服务端。客户端可以直接和服务端通信,但是不能直接和其他客户端通信。如何需要客户端之间彼此通信,需要在服务端建立一个相应的系统来完成这个功能。

 

绑定

 服务端socket被绑定到一个特殊的ip和端口。这就意味着服务端链接的唯一性。服务端想要和服务端建立socket链接,必须连接到与服务端相同ip和端口的服务端。

 

监听

socket建立后,它就会监听活动的客户端和想要创建链接的客户。这些客户端将被添加到队列中并且开始接受来自群组的信息。

 

php中的socket

使用php建立socket服务端需要一些优先级的配置。为了建立一个持久的链接,一个用php建立的socket服务端是不能用图形界面版本的php来操作的。一个socket链接必须在php支持命令行接口CLI)环境下运行。用php建立socket的第一步是判断是否有CLI版本的php

 

Windows中运行cmd

输入php –v

如出现php的版本信息则说明已安装

建立socket服务端

建立一个phpsocket服务端,开始是要创建一个文件并存储一些可访问地址。这个文件可以当作一个头文件来使用。

注意:你应该确保socket文件对外部网络是不可见的,因为当一些恶意用户试图修改或运行它时,可能会导致你的php无法正常工作。

 

下面我们通过一个简单的例子来理解socket的工作原理。

Socket服务端第一步要做的就是判断服务端ip地址和端口。如果你是本地运行的服务器,你是不需要判断你的物理ip地址的。取而代之的是,你可以使用local address

 

<?php

$host=”127.0.0.1”;

$port=”8888”;

 

端口号可以自己指定,但是必须确保其只被当前socket占用。

这个脚本需要需要确定PHP是在正常运行,因为它需要检查并且无限制的管理链接。这一步骤是通过 设置函数set_time_limit的参数为0来实现的,0的意思就是这段代码不会被停止,除非不存在了。

  set_time_limit(0);

这步完成后你可以来创建服务端socket链接了。

 $sock=socket_ctreate(AF_INET,SOCK_STREAMSOL_TOP);

函数的三个参数是用来定义链接的种类它是php的一些常量。对于这个例子而言他们不不重要,详细情况将在后面介绍。

$sock变量现在保存了一个激活的socket资源的id。下一步是绑定这个socket到刚刚的端口上。

Socket_bind($sock,$host,$port);

这一步完成后,你可以开始监听链接了。第一个参数是¥socket变量,他保存着socket资源的id。第二个参数是后台日志变量,在与客户端发生错误前,它会在告诉php队列中有多少条信息。这个变量不是一个必须的变量,因为一些系统将会定义或者重写这个值。例如,windows会设置自动设置并且默认会忽略任何用户提交的数据。

Socket_listen($sock,4);

这一步是仅仅是建立socket服务端。这意味着服务端开始并等待外来连接但是并不会做任何反应,当然这也是我们接下来要做的事情。

你需要调用socket_accept创建另一个socket来处理外来链接。

$childSocket=socket_accept($sock);

$childSocket变量是用来处理所有和客户端的通信。使用sock_read函数来读取通过连接传来的数据。

$incomingData=socket_read($childSocket,2048);

这个函数有两个参数。第一个参数是客户socket句柄,第二个参数是从客户端读取的数据量(译者:不知道是总量还是单次的)。这个参数有助于优化socket

socket_read函数会不断的读取相关信息并将其存储到$incomingData变量中直到数据量达到限制或者发现了相关:carriage return(\n),tab(\t),or \0Php将这些字符视作结束输入指令并且当发现他们时会自动换行。

 

回应客户端链接

 

当数据读取完成时,下一步就是对数据的处理和回应客户端。

例如下面是一个简单的例子:

If(substr($incomingData,0,-2)==”are you hungry?”)

{

 $response=”server Resonse> I could eat!\n”;

  socket_write($childSocket,$response,strlen($response));

}

socket_write函数有三个参数,第一个是其子socket资源id;第二个是返回给客户端的变量。第三个是可选变量,它是$response的长度。这个例子是当你调用php并且变量是“hungry”就会返回一个变量给客户端。正如你所看到的,这不是一个实际应用中程序,但是它却很清楚的解释了socket是怎么建立并且交互的。

这个例子的最后一步是,释放连接。

Socket_close($childSocket);

Socket_close($sock);

 

测试socket服务端

测试socket服务端可以用控制台(cmd窗口)来完成,如图所示,使用命令行 –f 来完成。

$ /path/to/php –f /path/to/socket/sampleSocket.php

为了能在控制平台上看到一些服务端的运行信息,我们在代码中加入:

<?php

…..

 print “starting socket server…\n”;

这样当你再次启动服务端时就会看到运行信息了。

当服务端运行后,你可以再开一个新窗口来连接客户端。

$talnet 127.0.0.1 8888

如果连接成功将会出现如下信息

$talnet 127.0.0.1 8888

Trying 127.0.0.1…

Connected to localhost.

….

这个程序只有在你输入“are you hungry?”时才会有反应。下面是完整代码:

 

<?php

$host=”127.0.0.1”;

$port=”8888”;

  set_time_limit(0);

print “starting socket server…\n”;

$sock=socket_ctreate(AF_INET,SOCK_STREAMSOL_TOP);

socket_bind($sock,$host,$port);

socket_listen($sock,4);

$childSocket=socket_accept($sock);

$incomingData=socket_read($childSocket,2048);

If(substr($incomingData,0,-2)==”are you hungry?”)

{

 $response=”server Resonse> I could eat!\n”;

  socket_write($childSocket,$response,strlen($response));

}

socket_close($childSocket);

socket_close($sock);

  ?>

链接会自动断开当消息返回后,因为没有后续的系统来处理额外的信息。在一般的应用中都会采用一些循环来获取多个信息。

创建持久的socket服务端

其实和前面例子差不多,只是利用循环来检查新的信息。

 

递归循环

Php不支持异步传输,但是你可以通过寻来来达到同样的效果

例如:

X=0;

While(x<50)

{

x++;

}

处理同一用户的多个信息

允许用户发送多条数据的关键是将socket_read函数放到循环中。

Code

当你询问“are you hungry?”时会返回指定字符串,当你输入其他除“exit”时,会返回大写的问题。这个简单的例子并不支持多客户端,所以当客户端关闭后,服务端也会关闭。


在flash中创建简单的socket 类


 1 package
 2 {
 3 Import flash.errors.*;
 4 Import flash.events.*;
 5 Import flash.net.Socket;
 6 Public class SimpleSocket extends Socket
 7  {
 8   public var host:String;
 9   public var port:uint;
10   private var socket:Socket;
11   public static var SOCK_CONNECTED:String="onSocketConnect";
12   public static var SOCK_IOERROR:String="onSocketError";
13   
14 function SimpleSocket(h:String,p:uint)
15 {
16 host=h;
17 port=p;
18 socket=this;
19 super(host,port);
20 initListeners(); 
21 }
22   
23 public function senMessage(str:String):void
24 {
25 if(connected)
26   {
27   socket.writeUTFBytes(str+"\n");
28    }
29  else
30    {
31    Trace("not connected!");
32    }
33 }// f end
34 public function readMessage():void
35  {
36   If(connected)
37   { var str:String=socket.readUTFBytes(socket.bytesAvilable);
38    Trace("socket Server Response:"+str);  
41 }
42 else 
43 {
44 trace("no message read,not connected!");
45 }
46   }
47 private function initListeners():void
48  {
49   socket.addEventListener(Event.CLOSE,closeHandler);
50   socket.addEventListener(Event.CONNECT,connectHandler);
51   socket.addEventListener(IOErrorEvent.IO_ERROR,ioErrorHandler);
52  }
53 private function closeHandler(event:Event):void
54 {
55 trace("connect to ["+host+"] closed");
56 }
57  
58 private function ioErrorHandler(event:IOErrorEvent):void
59 {
60 dispatchEvent(new Event(SOCK_IOERROR));
61 }
62 private function connectHandler(event:Event):void
63 {
64 trace("connected to ["+host+"]"); 
65 dispatchEvent(new Event(SOCK_CONNECTED));
66 }
67      
68 private function socketDataHandler(event:ProgressEvent):void
69 {
70 readMessage();
71 }
72   }
73 

 

posted on 2009-07-12 22:26  sungo  阅读(498)  评论(0编辑  收藏  举报