Soket是什么?
Soket
又叫套接字,是一个通信链的句柄,应用程序通过它来向网络发出请求或者响应请求。其本质是是应用层与TCP/IP
协议族通信的中间软件抽象层,它是一组接口。
工作位置如下:
工作原理如下:
过程详解:
服务器端先初始化Socket
,然后与端口绑定,对端口进行监听,调用accept
阻塞,等待客户端连接。在这时如果有个客户端初始化一个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()
删除一个已经分配的iovecsocket_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()
这个函数发送数据到已连接的socketsocket_sendmsg()
发送消息到socketsocket_sendto()
发送消息到指定地址的socketsocket_set_block()
在socket里设置为块模式socket_set_nonblock()
socket里设置为非块模式socket_set_option()
设置socket选项socket_shutdown()
这个函数允许你关闭读、写、或者指定的socketsocket_strerror()
返回指定错误号的详细错误socket_write()
写数据到socket缓存socket_writev()
写数据到分散/聚合数组
使用示例
服务端
/**
* socket服务端全过程
*/
if (!extension_loaded('sockets')) {
die('socket扩展还未加载!');
}
//防止超时
set_time_limit(0);
$ip = '127.0.0.1';
$port = 1935;
//1、创建套接字
if (($sock = socket_create(AF_INET , SOCK_STREAM , SOL_TCP )) === false) {
echo "创建socket失败,原因是:" . socket_strerror(socket_last_error()) . "\n" ;
}
//2、绑定address到socket
if (socket_bind($sock, $ip, $port) === false) {
echo "socket绑定地址失败,原因是:" . socket_strerror(socket_last_error()) . "\n" ;
}
//3、告知socket开始监听,第二个参数指定队列中最多可容纳的等待接受的传入连接数
if (socket_listen($sock, 5) === false) {
echo "socket监听失败,原因是:" . socket_strerror(socket_last_error()) . "\n" ;
}
do {
//4、接收连接请求并调用另一个socket处理客户端和服务器间的信息
if (($msgsock = socket_accept($sock)) === false) {
echo "accept失败,原因是: " . socket_strerror(socket_last_error($sock)) . "\n";
break;
}
//5、把缓冲区内容写入socket
$msg = "服务端:测试成功!\n";
socket_write($msgsock, $msg, strlen($msg));
//6、从socket中读取数据
if (($buf = socket_read($msgsock, 2048, PHP_NORMAL_READ)) === false) {
echo "从socket中读取数据失败,原因是: " . socket_strerror(socket_last_error($msgsock)) . "\n";
break;
}
$talkback = "客户端发的消息是:" . $buf . "\n";
socket_write($msgsock, $talkback, strlen($talkback));
echo " $buf \n";
} while (true);
//关闭socket
socket_close ($sock);
客户端:
/**
* socket客户端全过程
*/
if (!extension_loaded('sockets')) {
die('socket扩展还未加载!');
}
error_reporting(E_ALL);
set_time_limit(0);
echo "TCP/IP Connection\n";
$service_port = 1935;
$ip = "127.0.0.1";
//1、创建socket
$socket = socket_create ( AF_INET , SOCK_STREAM , SOL_TCP );
if ( $socket === false ) {
echo "socket_create() 失败,原因是:" . socket_strerror ( socket_last_error ()) . "\n" ;
} else {
echo "OK.\n" ;
}
echo "尝试连接到:' $ip ' ,端口: ' $service_port '..." ;
//2、连接socket
$result = socket_connect ( $socket , $ip , $service_port );
if ( $result === false ) {
echo "socket_connect()失败.\n原因是: ( $result ) " . socket_strerror ( socket_last_error ( $socket )) . "\n" ;
} else {
echo "OK.\n" ;
}
$in = "HEAD / HTTP/1.1\r\n" ;
$in .= "Host: www.test.com\r\n" ;
$in .= "Connection: Close\r\n\r\n" ;
$out = '' ;
echo "Sending HTTP HEAD request..." ;
//3、发送数据
socket_write($socket, $in, strlen($in));
echo "OK.\n" ;
echo "Reading response:\n\n" ;
//4、读取返回数据
while ($out = socket_read($socket, 2048)) {
echo $out;
}
echo "Closing socket..." ;
//5、关闭socket
socket_close($socket);
echo "OK.\n\n" ;
然后在cmd
上先用php执行服务端代码,确保soket创建成功,并处于等待连接状态(运行后可使用netstat -ano
命令查看指定端口是否处于监听状态),然后再运行客户端代码查看是否连接正常。
注意
由于php语言本身的特性决定了其只适合做soket的客户端(比如连接Mysql就是通过soket进行的),而不适合做服务端,因为soket只要面向底层和网络服务开发,而用c语言、java等来实现的话能更好的操作底层,并且在网络服务开发中遇到的问题也有更完善、成熟的解决方案。
原文:http://www.cnblogs.com/thinksasa/archive/2013/02/26/2934206.html