php Socket 基础

纯参考,突然让我想起以前的ugia.cn提供的upu(还是ugu来着?不记得了)上传组件。
利用socket监听,然后上传,利用流来写入文件。值得参考一下,想着ASP可以利用 xmlhttp进行大文件上传,想来PHP应该也可以,啥时候研究一下。
以下内容就是socket的初学者要看的文章,我也要看。呵呵

内容如下,未做删减 http://phpsoho.com/article/php/200809/11-245.html
PHP 使 用Berkley的socket库来创建它的连接。socket只不过是一个数据结构。你使用这个socket数据结构去开始一个客户端和服务器之间的会 话。这个服务器是一直在监听准备产生一个新的会话。当一个客户端连接服务器,它就打开服务器正在进行监听的一个端口进行会话。这时,服务器端接受客户端的 连接请求,那么就进行一次循环。现在这个客户端就能够发送信息到服务器,服务器也能发送信息给客户端。
产生一个Socket,你需要三个变量:一个协议、一个socket类型和一个公共协议类型。产生一个socket有三种协议供选择,继续看下面的内容来获取详细的协议内容。
定义一个公共的协议类型是进行连接一个必不可少的元素。下面的表我们看看有那些公共的协议类型。

表一:协议

名字/常量     描述
AF_INET 这是大多数用来产生socket的协议,使用TCP或UDP来传输,用在IPv4的地址
AF_INET6     与上面类似,不过是来用在IPv6的地址
AF_UNIX 本地协议,使用在Unix和Linux 系统上,它很少使用,一般都是当客户端和服务器在同一台机器上的时候使用

表二:Socket类型

名字/常量     描述
SOCK_STREAM 这个协议是按照顺序的、可靠的、数据完整的基于字节流的连接。这是一个使用最多的socket类型,这个socket是使用TCP来进行传输。
SOCK_DGRAM 这个协议是无连接的、固定长度的传输调用。该协议是不可靠的,使用UDP来进行它的连接。
SOCK_SEQPACKET 这个协议是双线路的、可靠的连接,发送固定长度的数据包进行传输。必须把这个包完整的接受才能进行读取。
SOCK_RAW 这个socket类型提供单一的网络访问,这个socket类型使用ICMP公共协议。(ping、traceroute使用该协议)
SOCK_RDM 这个类型是很少使用的,在大部分的操作系统上没有实现,它是提供给数据链路层使用,不保证数据包顺序

表三:公共协议

名字/常量     描述
ICMP 互联网控制消息协议,主要使用在网关和主机上,用来检查网络状况和报告错误信息
UDP      用户数据报文协议,它是一个无连接,不可靠的传输协议
TCP 传输控制协议,这是一个使用最多的可靠的公共协议,它能保证数据包能够到达接受者那儿,如果在传输过程中发生错误,那么它将重新发送出错数据包。
现 在你知道了产生一个socket的三个元素,那么我们就在php中使用socket_create()函数来产生一个socket。这个 socket_create()函数需要三个参数:一个协议、一个socket类型、一个公共协议。socket_create()函数运行成功返回一个 包含socket的资源类型,如果没有成功则返回false。
Resourece socket_create(int protocol, int socketType, int commonProtocol);
现在你产生一个socket,然后呢?php提供了几个操纵socket的函数。你能够绑定socket到一个IP,监听一个socket的通信,接受一个socket;现在我们来看一个例子,了解函数是如何产生、接受和监听一个socket。

$commonProtocol
 = getprotobyname
(
“tcp”)
;//使用公共协议名字来获取一个协议类型

$socket = socket_create ( AF_INET, SOCK_STREAM, $commonProtocol ) ;//产生一个socket并且返回一个socket资源的实例
socket_bind ( $socket , ‘localhost’, 1337 ) ;//绑定socket到本地计算机
socket_listen ( $socket ) ;//监听所有进来的socket连接
// More socket functionality to come

面这个例子产生一个你自己的服务器端。例子第一行

$commonProtocol
 = getprotobyname

(
“tcp”)
;

使用公共协议名字来获取一个协议类型。在这里使用的是TCP公共协议,如果你想使用UDP或者ICMP协议,那么你应该把 getprotobyname()函数的参数改为“udp”或“icmp”。还有一个可选的办法是不使用getprotobyname()函数而是指定 SOL_TCP或SOL_UDP在socket_create()函数中。
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
例子的第二行是产生一个socket并且返回一个socket资源的实例。在你有了一个socket资源的实例以后,你就必须把socket绑定到一个IP地址和某一个端口上。

socket_bind

(
$socket
, ‘localhost’, 1337
)
;


在这里你绑定socket到本地计算机(127.0.0.1)和绑定socket到你的1337端口。然后你就需要监听所有进来的socket连接。

socket_listen

(
$socket
)
;


在第四行以后,你就需要了解所有的socket函数和他们的使用。

表四:Socket函数

函数名      描述
socket_accept ( ) 接受一个Socket连接
socket_bind ( ) 把socket绑定在一个IP地址和端口上
socket_clear_error ( ) 清除socket的错误或者最后的错误代码
socket_close ( ) 关闭一个socket资源
socket_connect ( ) 开始一个socket连接
socket_create_listen ( ) 在指定端口打开一个socket监听
socket_create_pair ( ) 产生一对没有区别的socket到一个数组里
socket_create ( ) 产生一个socket,相当于产生一个socket的数据结构
socket_get_option ( ) 获取socket选项
socket_getpeername ( ) 获取远程类似主机的ip地址
socket_getsockname ( ) 获取本地socket的ip地址
socket_iovec_add ( ) 添加一个新的向量到一个分散/聚合的数组
socket_iovec_alloc ( ) 这个函数创建一个能够发送接收读写的iovec数据结构
socket_iovec_delete ( ) 删除一个已经分配的iovec
socket_iovec_fetch ( ) 返回指定的iovec资源的数据
socket_iovec_free ( ) 释放一个iovec资源
socket_iovec_set ( ) 设置iovec的数据新值
socket_last_error ( ) 获取当前socket的最后错误代码
socket_listen ( ) 监听由指定socket的所有连接
socket_read ( ) 读取指定长度的数据
socket_readv ( ) 读取从分散/聚合数组过来的数据
socket_recv ( ) 从socket里结束数据到缓存
socket_recvfrom ( ) 接受数据从指定的socket,如果没有指定则默认当前socket
socket_recvmsg( ) 从iovec里接受消息
socket_select ( ) 多路选择
socket_send ( ) 这个函数发送数据到已连接的socket
socket_sendmsg( ) 发送消息到socket
socket_sendto ( ) 发送消息到指定地址的socket
socket_set_block( ) 在socket里设置为块模式
socket_set_nonblock ( ) socket里设置为非块模式
socket_set_option ( ) 设置socket选项
socket_shutdown ( ) 这个函数允许你关闭读、写、或者指定的socket
socket_strerror( ) 返回指定错误号的详细错误
socket_write ( ) 写数据到socket缓存
socket_writev ( ) 写数据到分散/聚合数组

以上所有的函数都是PHP中关于socket的,使用这些函数,你必须把你的socket打开,如果你没有打开,请编辑你的php.ini文件,去掉下面这行前面的注释:

extension=php_sockets.dll

如果你无法去掉注释,那么请使用下面的代码来加载扩展库:

if
(
!extension_loaded

(
‘sockets’)
)

{
if ( strtoupper ( substr ( PHP_OS , 3 ) ) == “WIN”)
{
dl ( ‘php_sockets.dll’) ;
} else {
dl ( ‘sockets.so’) ;
}
}

如果你不知道你的socket是否打开,那么你可以使用phpinfo()函数来确定socket是否打开。你通过查看phpinfo信息了解socket是否打开。
查看phpinfo()关于socket的信息

◆ 产生一个服务器

现在我们把第一个例子进行完善。你需要监听一个指定的socket并且处理用户的连接。

$commonProtocol
 = getprotobyname

(
"tcp"
)
;
$socket = socket_create ( AF_INET, SOCK_STREAM, $commonProtocol ) ;
socket_bind ( $socket , 'localhost' , 1337 ) ;
socket_listen ( $socket ) ;
// Accept any incoming connections to the server
$connection = socket_accept ( $socket ) ;
if ( $connection ) {
socket_write ( $connection , "You have connected to the socket.../n /r " ) ;
}

你应该使用你的命令提示符来运行这个例子。理由是因为这里将产生一个服务器,而不是一个Web页面。如果你尝试使用Web浏览器来运行这个脚本,那么很有可能它会超过30秒的限时。你可以使用下面的代码来设置一个无限的运行时间,但是还是建议使用命令提示符来运行。

set_time_limit

(
0
)
;

在你的命令提示符中对这个脚本进行简单测试:

Php.exe example01_server.php

如果你没有在系统的环境变量中设置php解释器的路径,那么你将需要给php.exe指定详细的路径。当你运行这个服务器端的时候,你能够通过远程登陆(telnet)的方式连接到端口1337来测试这个服务器。

上面的服务器端有三个问题:

1. 它不能接受多个连接。
2. 它只完成唯一的一个命令。
3. 你不能通过Web浏览器连接这个服务器。

这个第一个问题比较容易解决,你可以使用一个应用程序去每次都连接到服务器。但是后面的问题是你需要使用一个Web页面去连接这个服务器,这个比较困难。你可以让你的服务器接受连接,然后些数据到客户端(如果它一定要写的话),关闭连接并且等待下一个连接。
在上一个代码的基础上再改进,产生下面的代码来做你的新服务器端:

// Set up our socket 

$commonProtocol = getprotobyname ( "tcp" ) ;
$socket = socket_create ( AF_INET, SOCK_STREAM, $commonProtocol ) ;
socket_bind ( $socket , 'localhost' , 1337 ) ; //socket_bind() 把socket绑定在一个IP地址和端口上
socket_listen ( $socket ) ;
// Initialize the buffer
$buffer = "NO DATA" ;
while ( true ) {
// Accept any connections coming in on this socket
$connection = socket_accept ( $socket ) ;//socket_accept() 接受一个Socket连接
printf ( "Socket connected/r /n " ) ;
// Check to see if there is anything in the buffer
if ( $buffer != "" ) {
printf ( "Something is in the buffer...sending data.../r /n " ) ;
socket_write ( $connection , $buffer . "/r /n " ) ; //socket_write() 写数据到socket缓存
printf ( "Wrote to socket/r /n " ) ;
} else {
printf ( "No Data in the buffer/r /n " ) ;
}
// Get the input
while ( $data = socket_read ( $connection , 1024 , PHP_NORMAL_READ) ) //socket_read() 读取指定长度的数据
{
$buffer = $data ;
socket_write ( $connection , "Information Received/r /n " ) ;
printf ( "Buffer: " . $buffer . "/r /n " ) ;
}
socket_close ( $connection ) ; //socket_close() 关闭一个socket资源
printf ( "Closed the socket/r /n /r /n " ) ;
}

这个服务器端要做什么呢?它初始化一个socket并且打开一个缓存收发数据。它等待连接,一旦产生一个连接,它将打印“Socket connected”在服务器端的屏幕上。这个服务器检查缓冲区,如果缓冲区里有数据,它将把数据发送到连接过来的计算机。然后它发送这个数据的接受信 息,一旦它接受了信息,就把信息保存到数据里,并且让连接的计算机知道这些信息,最后关闭连接。当连接关闭后,服务器又开始处理下一次连接。


◆ 产生一个客户端


处理第二个问题是很容易的。你需要产生一个php页连接一个socket,发送一些数据进它的缓存并处理它。然后你有个处理后的数据在还顿,你能够发送你的数据到服务器。在另外一台客户端连接,它将处理那些数据。
下面的例子示范了使用socket:

// Create the socket and connect 

$socket = socket_create ( AF_INET, SOCK_STREAM, SOL_TCP) ;
$connection = socket_connect ( $socket ,’localhost’, 1337 ) ;
while ( $buffer = socket_read ( $socket , 1024 , PHP_NORMAL_READ) ) {
if ( $buffer == “NO DATA”) {
echo ( “<p>NO DATA</p>”) ;
break ;
} else {
// Do something with the data in the buffer
echo ( “<p>Buffer Data: “ . $buffer . “</p>”) ;
}
}
echo ( “<p>Writing to Socket</p>”) ;
// Write some test data to our socket
if ( !socket_write ( $socket , “SOME DATA/r/n”) ) {
echo ( “<p>Write failed</p>”) ;
}
// Read any response from the socket
while ( $buffer = socket_read ( $socket , 1024 , PHP_NORMAL_READ) ) {
echo ( “<p>Data sent was: SOME DATA<br> Response was:” . $buffer . “</p>”) ;
}
echo ( “<p>Done Reading from Socket</p>”) ;

这个例子的代码演示了客户端连接到服务器。客户端读取数据。如果这是第一时间到达这个循环的首次连接,这个服务器将发送“NO DATA”返回给客户端。如果情况发生了,这个客户端在连接之上。客户端发送它的数据到服务器,数据发送给服务器,客户端等待响应。一旦接受到响应,那么 它将把响应写到屏幕上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PHP socket是一种用于网络编程的功能强大的工具。它允许开发者创建基于TCP或UDP协议的网络连接,并通过这些连接进行数据传输。使用PHP socket,你可以创建服务器端和客户端应用程序,实现实时通信、网络游戏、远程控制等功能。 在PHP中,你可以使用socket函数库来操作socket。以下是一个简单的例子,展示了如何创建一个简单的TCP服务器和客户端: 服务器端代码(server.php): ```php <?php // 创建socket $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); // 绑定IP地址和端口 socket_bind($socket, '127.0.0.1', 8080); // 监听连接 socket_listen($socket); // 接受客户端连接 $client = socket_accept($socket); // 从客户端接收数据 $data = socket_read($client, 1024); // 处理接收到的数据 // ... // 发送响应给客户端 $response = 'Hello, client!'; socket_write($client, $response, strlen($response)); // 关闭连接 socket_close($client); socket_close($socket); ?> ``` 客户端代码(client.php): ```php <?php // 创建socket $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); // 连接到服务器 socket_connect($socket, '127.0.0.1', 8080); // 发送数据给服务器 $data = 'Hello, server!'; socket_write($socket, $data, strlen($data)); // 接收服务器响应 $response = socket_read($socket, 1024); // 处理服务器响应 // ... // 关闭连接 socket_close($socket); ?> ``` 这只是一个简单的示例,你可以根据需求来扩展和改进代码。希望对你有所帮助!如果你有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值