PHP网页编程之PHP套接字编程
可以在书上很方便地做标记,及时记下自己的心得体会。编程 作者:久隆信息/张晓刚套接字编程,普通利用c或c++。出格的在web使用法式开辟中,经常使用perl完成套接字。除此之外,用php停止套接字编程也是一个选择。Php可以胜任吗?固然可以。Php是一门高质量的web使用法式开辟言语,他的很多特征可以处置浩瀚的义务,收集编程也不破例。
1. 了解套接字
Mail、ftp、telnet、name和finger这些办事都是在一个公用的公然的端口上供应的,经由过程毗连到这些端口,客户法式就可以够会见这些办事。这与实际生涯是类似的――当需求干洗衣服的时分,找干洗店;当需求取钱的时分,去银行,等等。除公用于特定办事器的端口外,盘算机还有其它的端口让法式员创立他们本人的办事器。
端口通常为编号的,经由过程指定办事器的端标语,客户法式可以毗连到该端口上。每种办事器或端口要有特定的协定,为了让客户的恳求可以被了解和呼应,客户必需以这类办事器独有的体例构成客户恳求。
Socket是收集上运转的两个法式间双向通讯毗连的一端。Socket这个词的普通意义是天然的某人工的插口,如家用电器的电源插口等。
客户法式可以向Socket写恳求,办事器将处置此恳求,然后经由过程Socket把了局前往给客户。
Socket是一种底层毗连。客户机和办事器经由过程写入到Socket的字撙节停止通讯。它们必需有配合的协定,也就是说,经由过程Socket互相传送信息时所用的言语必需是协议好的。
2. Socket创立毗连的进程
创立进程以下:(connection-oriented)
server 方进程 client 方进程
socket() socket()
| |
bind() bind()
| |
listen() |
| |
accept()<------------------connect()
| |
recv()/send() <----------> send()/recv()
3. Php 根基套接字挪用:
3.1. 根基套接字挪用
创立套接字--socket();
绑定本机端口--bind();
创立毗连--connect(),accept();
侦听端口--listen();
数据传输--send(),recv();
输出/输入多路复用--select();
封闭套接字--closesocket()
3.2. php供应的套接字挪用:
承受毗连-―accept connect()
绑定端口―bind ()
封闭套接字―close()
初始化毗连―connect()
侦听端口―listen()
读取套接字―read()
创立套接字―socket()
写套接字―write()
4. 根基使用
4.1. 一个复杂的TCP办事器
1 #!/usr/local/bin/php -q
2
3 <?php
4 /*
5 * We don't want any time-limit for how the long can hang
6 * around, waiting for connections:
7 */
8 set_time_limit(0);
9
10 /* Create a new socket: */
11 if( ($sock = socket( AF_INET, SOCK_STREAM, 0 )) < 0 )
12 {
13 print strerror( $sock ) . "n";
14 exit(1);
15 }
16
17 /* Bind the socket to an address and a port: */
18 if( ($ret = bind( $sock, "10.31.172.77", 10000 )) < 0 )
19 {
20 print strerror( $ret ) . "n";
21 exit(1);
22 }
23
24 /*
25 * Listen for incoming connections on $sock.
26 * The '5' means that we allow 5 queued connections.
27 */
28 if( ($ret = listen( $sock, 5 )) < 0 )
29 {
30 print strerror( $ret ) . "n";
31 }
32
33 /* Accept incoming connections: */
34 if( ($msgsock = accept_connect( $sock )) < 0)
35 {
36 print strerror( $msgsock ) . "n";
37 exit(1);
38 }
39
40 /* Send the welcome-message: */
41 $message = "Welcome to my TCP-server!n";
42 if( ($ret = write( $msgsock, $message, strlen($message)) ) < 0 )
43 {
44 print strerror( $msgsock ) . "n";
45 exit(1);
46 }
47
48 /* Read/Receive some data from the client: */
49 $buf = '';
50 if( ($ret = read( $msgsock, $buf, 128 )) < 0 )
51 {
52 print strerror( $ret ) . "n";
53 exit(1);
54 }
55
56 /* Echo the received data back to the client: */
57 if( ($ret = write( $msgsock, "You said: $bufn", strlen("You said: $bufn")) ) < 0 )
58 {
59 print strerror( $ret ) . "n";
60 exit(1);
61 }
62
63 /* Close the communication-socket: */
64 close( $msgsock );
65
66 /* Close the global socket: */
67 close( $sock );
68 ?>
第8行:利用set_time_limit设定法式履行工夫为无穷以守候毗连;
11-15: 创立一个套接字;
18-22: 把创立的套接字与IP及端口绑定;
28-31: 侦听端口;
34-38: 承受毗连;
41-46: 显示接待信息;
49-54: 读取客户端信息;
57-61: 向客户端回显信息;
63-67: 封闭套接字
4.2. TCP办事器的运转
上边这个tcp办事器的运转请求php编译成cgi注释体例,而且编译时到场--enable-sockets。
假如你已编译成cgi注释体例运转,然而利用号令php -m列出的项目没有sockets,则申明你需求从头编译php。当这些请求到达后你就能够运转这个办事器了
启动办事器:
./filename.php
然后就能够利用telnet登录了。
telnet 10.31.172.77 10000
你的终端大将显示:
Trying 10.31.172.77...
Connected to 10.31.172.77.
Escape character is '^]'.
Welcome to my TCP server!
然后输出一些器材,并回车:
Hello
You said: Hello
Connection closed by foreign host
你也能够修正一下这个法式,让它像phpmanual上的谁人例子,只要当客户端输出“quit“的时分才封闭毗连。
5. 其他使用
5.1. 聊天室使用
5.1.1. 罕见的聊天室完成
普通的聊天室的完成常利用的办法是利用框架页面,然后对个中一个用于显示说话内容的框架利用html的体例刷新,例如:
<meta http-equiv=“refresh” content=”3;http://www.jite.net”>
利用这类体例会招致阅读器端不休的向办事器端收回恳求,当有大批的恳求时就会使得办事器运转效力下降。如许的聊天室明显是有设计坏处的。
然而假如利用socket的体例完成聊天室,情形就分歧了。
5.1.2. 利用socket完成聊天室
咱们要会商的聊天室十分复杂,只是一个道理上的完成。
它是一个 client/server 布局的法式, 起首启动 server, 然后用户利用 client 停止毗连. client/server 布局的长处是速度快, 弱点是当 server 停止更新时, client 也必须更新.
初始化 server, 使server 进入监听形态: (以下只是完成道理,其实不触及详细法式)
$socket = socket( AF_INET,SOCK_STREAM, 0);
// 起首创立一个 socket, 族为 AF_INET, 类型为 SOCK_STREAM.
// AF_INET = ARPA Internet protocols 即便用 TCP/IP 协定族
// SOCK_STREAM 类型供应了按次的, 牢靠的, 基于字撙节的全双工毗连.
// 因为该协定族中只要一个协定, 因而第三个参数为 0
bind ($sock, $address, $port)
// 再将这个 socket 与某个地址停止绑定.
listen( sockfd, MAX_CLIENT)
// 地址绑定以后, server 进入监听形态.
// MAX_CLIENT 是可以同时创立毗连的 client 总数.
server 进入 listen 形态后, 守候 client 创立毗连。
Client端要创立毗连起首也需求初始化毗连:
$socket= socket( AF_INET,SOCK_STREAM,0))
// 一样的, client 也先创立一个 socket, 其参数与 server 不异.
connect ($socket, $address, $service_port)
// client 利用 connect 创立一个毗连.
当 client 创立新毗连的恳求被送到Server端时, server 利用 accept 来承受该毗连:
accept_connect($sock)
// accept 前往一个新的文件描写符.
在 server 进入 listen 形态以后, 因为能够有多个用户恳求毗连,所以法式需求同时对这些用户停止操作,并在它们之间完成信息互换。这在完成上称为I/O多路复用手艺。
I/O多路复用手艺的办法就不是本文所要叙说的内容了,若有乐趣请参考相干书本。
5.2. 一个基于web的旧事组阅读器
在php中可使用fsockopen翻开一个tcp socket毗连
int fsockopen (string hostname, int port [, int errno [, string errstr [, double timeout]]])
有关此函数的利用请参考php手册。
会见旧事组办事,需求利用一个协定叫NNTP,即Network News Transfer Protocol。
这个协定有一个公用的RFC描写,它位于 http://www.w3.org/Protocols/rfc977/rfc977.html。
该文档具体的申明了若何统一个nntp办事器对话及若何利用号令完成义务。
5.2.1. 毗连一个办事器
<?php
$cfgServer = "news.php.net";
$cfgPort = 119;
$cfgTimeOut = 10;
// open a socket
if(!$cfgTimeOut)
// without timeout
$usenet_handle = fsockopen($cfgServer, $cfgPort);
else
// with timeout
$usenet_handle = fsockopen($cfgServer, $cfgPort, &$errno, &$errstr, $cfgTimeOut);
if(!$usenet_handle) {
echo "Connexion failedn";
exit();
}
else {
echo "Connectedn";
$tmp = fgets($usenet_handle, 1024);
}
?>
5.2.2. 同办事器停止对话
在后面,咱们已同办事器毗连上了,假设咱们要从某一旧事组当选取10条比来的旧事,该怎样办呢?
RFC977指出,选择一个旧事组利用group号令:
GROUP ggg
<?php
//$cfgUser = "xxxxxx";
//$cfgPasswd = "yyyyyy";
$cfgNewsGroup = "alt.php";
// identification required on private server
if($cfgUser) {
fputs($usenet_handle, "AUTHINFO USER ".$cfgUser."n");
$tmp = fgets($usenet_handle, 1024);
fputs($usenet_handle, "AUTHINFO PASS ".$cfgPasswd."n");
$tmp = fgets($usenet_handle, 1024);
// check error
if($tmp != "281 Okrn") {
echo "502 Authentication errorn";
exit();
}
}
// select newsgroup
fputs($usenet_handle, "GROUP ".$cfgNewsGroup."n");
$tmp = fgets($usenet_handle, 1024);
if($tmp == "480 Authentication required for commandrn") {
echo "$tmpn";
exit();
}
$info = split(" ", $tmp);
$first = $info;
$last = $info;
print "First : $firstn";
print "Last : $lastn";
?>
5.2.3. 读取旧事
读取旧事的号令是article,详细用法请参考RFC977,这里就不供应例程了。
6. 跋文
我觉得前次写了一篇,此次就能够免了。离交稿日期没几天了,于荣赋来约稿。程稿仓皇,不免有错,请见谅,而且指出。
7. 参考文献:
廖斌,《php的守护法式编程》;
w3c,《RFC977》;
Daniel Solin,Introduction to Socket Programming with PHP;
学习数据库了,MYSQL可算是PHP的黄金搭档了,不过,虽然话是这么说,你也可能恨不得把MYSQL给生吞活剥了,因为这一行一列的东东简直让自己头晕目眩。 这些中手常用的知识,当你把我说的这些关键字都可以熟练运用的时候,你可以选择自己 说点我烦的低级错误吧,曾经有次插入mysql的时间 弄了300年结果老报错,其实mysql的时间是有限制的,大概是到203X年具体的记不清啦,囧。 使用zendstdio 写代码的的时候,把tab 的缩进设置成4个空格是很有必要的 本文当是我的笔记啦,遇到的问题随时填充 小鸟是第一次发帖(我习惯潜水的(*^__^*) 嘻嘻……),有错误之处还请大家批评指正,另外,前些日子听人说有高手能用php写驱动程序,真是学无止境,人外有人,天外有天。 我要在声明一下:我是个菜鸟!!我对php这门优秀的语言也是知之甚少。但是我要在这里说一下php在网站开发中最常用的几个功能: 要进行开发,搭建环境是首先需要做的事,windows下面我习惯把环境那个安装在C盘下面,因为我配的环境经常出现诡异事件,什么事都没做环境有的时候就不能用啦。 ,熟悉html,能用div+css,还有javascript,优先考虑linux。我在开始学习的时候,就想把这些知识一起学习,我天真的认为同时学习能够互相呼应,因为知识是相通的。 我要在声明一下:我是个菜鸟!!我对php这门优秀的语言也是知之甚少。但是我要在这里说一下php在网站开发中最常用的几个功能: 找到的的资料很多都是在论坛里的,需要注册,所以我一般没到一个论坛都注册一个id,所有的id都注册成一样的,这样下次再进来的时候就不用重复注册啦。当然有些论坛的某些资料是需要的付费的。 为了以后维护的方便最好是代码上都加上注释,“予人方便,自己方便”。此外开发文档什么的最好都弄齐全。我觉得这是程序员必备的素质。虽然会消耗点很多的时间。但是确实是非常有必要的。 最后祝愿,php会给你带来快乐的同时 你也会给他带来快乐。 当留言板完成的时候,下步可以把做1个单人的blog程序,做为目标, 当留言板完成的时候,下步可以把做1个单人的blog程序,做为目标, 再就是混迹于论坛啦,咱们的phpchina的论坛就很强大,提出的问题一般都是有达人去解答的,以前的帖子也要多看看也能学到不少前辈们的经验。别的不错的论坛例如php100,javaeye也是很不错的。 学好程序语言,多些才是王道,写两个小时代码的作用绝对超过看一天书,这个我是深有体会(顺便还能练打字速度)。 先学习php和mysql,还有css(html语言很简单)我认为现在的效果比以前的方法好。 最后祝愿,php会给你带来快乐的同时 你也会给他带来快乐。
页:
[1]