我正在使用PHP开发套接字程序。
Problems : Cannot detect to a client is disconnected using socket_recv() method.
我的源已被配置为3个文件。 2个文件是服务器文件,1个文件是客户端文件。 这是我的详细代码。
socket.server.php
<?php
class SocketServer {
public $address; // socket address
public $port; // socket port
public $handle; // openned file handler
public $fileurl; // File url for logs
public $echoflg; // Echo or unless flag
public $ssock; // TCP stream server socket resource
public $clients; // Client array
function __construct() {
$this->address = "10.76.15.2";
$this->port = 6666;
$this->handle = FALSE;
$this->echoflg = FALSE;
$this->clients = array();
}
/**
* Write in log files for logging
* @param $log
*
* @return void
*/
public function logs($log){
if($this->handle){
$log = "[".date("Y-m-d H:i:s")."] ".$log."\r\n\r\n";
fwrite($this->handle, $log);
if($this->echoflg) echo $log."</br></br>";
}
}
/**
* Get Socket Last Error Message
*
* @return SocketLastError
*/
public function getSocketError($sock){
return socket_strerror(socket_last_error($sock));
}
/**
* Close the server socket
*
* @return void
*/
public function closeServerSocket(){
socket_close($this->ssock);
$this->logs("---------------- SERVER CLOSED -----------------");
}
/**
* Creating, Binding, Listening, Non Blocking for TCP stream socket
*
* @return Bool
*/
public function initServer(){
$this->handle = fopen($this->fileurl, "a+"); // open log file
$this->logs("============== SERVER STARTING ===============");
//set_time_limit (0); // Set time limit to indefinite execution
/** Create a TCP Stream socket **/
if(($this->ssock = socket_create(AF_INET, SOCK_STREAM, 0)) === FALSE){
$this->logs("Fail to Create a TCP Stream socket\r\n".socket_strerror(socket_last_error()));
return FALSE;
}
else{
$this->logs("Success to Create a TCP Stream socket");
}
/** Bind the socket to an address/port **/
if(socket_bind($this->ssock, $this->address, $this->port) === FALSE){
$this->logs("Fail to bind to address\r\n".$this->getSocketError($this->ssock));
$this->closeServerSocket();
return FALSE;
}
else{
$this->logs("Success to bind to address");
}
/** Start listening for connections **/
if(socket_listen($this->ssock) === FALSE){
$this->logs("Fail to listen for connections\r\n".$this->getSocketError($this->ssock));
$this->closeServerSocket();
return FALSE;
}
else{
$this->logs("Success to listen for connections");
}
/** Non block socket type **/
if(socket_set_nonblock($this->ssock) === FALSE){
$this->logs("Fail to set for Non block socket type\r\n".$this->getSocketError($this->ssock));
$this->closeServerSocket();
return FALSE;
}
else{
$this->logs("Success to set for Non block socket type");
}
$this->logs("+++++++++++++++ SERVER STARTED ++++++++++++++++");
return TRUE;
}
/**
* Read a data from client on socket
* @param $csock - client socket connected to server
*
* @return $msg
*/
public function readMessage($csock, $length=1024){
$msg = "";
$tmp = "";
//$this->logs("Reading");
/*
while(($tmp = socket_read($csock, 2048, PHP_NORMAL_READ)) > 0){
//$this->logs($tmp);
$msg .= $tmp;
}
if($tmp === FALSE) return FALSE;
else return $msg;
*/
/*
while(socket_recv($csock, $message, 1024, 0) !== FALSE){
if($message != null){
$msg .= $message;
}
};
*/
while(($flag = socket_recv($csock, $buf, $length, 0)) > 0){
$asc = ord(substr($buf, -1));
if ($asc == 0) {
$msg .= substr($buf, 0, -1);
break;
}else{
$msg .= $buf;
}
//$msg .= $buf;
}
if($flag < 0){ // Error
$this->logs("Error on reading : ".$this->getSocketError($this->ssock));
return FALSE;
}
elseif($flag === 0){ // client disconnected
$this->logs("Client disconnected");
return FALSE;
}
else{
//$this->logs("Reading finished");
return $msg;
}
/*
//$msg = socket_recv($csock, $message, 2048, 0);
$this->logs("Reading finished");
if($msg === FALSE){
return FALSE;
}
return $msg;
*/
}
/**
* Write to the client on socket
* @param $csock
* @param $msg
*
* @return Bool
*/
public function sendMessage($csock, $msg){
$msg = $msg."\n\r";
$length = strlen($msg);
if(socket_write($csock, $msg, $length) === FALSE){
return FALSE;
}
else{
return TRUE;
}
/*
while(true) {
$sent = socket_write($csock, $msg."\n\r", $length = strlen($msg."\n\r"));
if($sent === FALSE) {
return FALSE;
}
if($sent < $length) {
$msg = substr($msg, $sent);
$length -= $sent;
$this->logs("Message truncated: Resending: $msg");
}
else{
return TRUE;
}
}
return FALSE;
*/
}
/**
* Re-arrange a connected clients list
*
* @return void
*/
public function resetClientList(){
$tmp = array();
$i = 0;
if(count($this->clients)){
foreach ($this->clients as $k => $v){
$tmp[$i] = $v;
$i++;
}
$this->clients = $tmp;
}
}
/**
* Detect a new client and accpet or close
*
* @return void
*/
public function acceptClient(){
$new_index = count($this->clients);
if($csock = socket_accept($this->ssock)){
$this->logs("Trying index : ".$new_index);
if(is_resource($csock)){
if(($msg = $this->readMessage($csock)) === FALSE){
$this->logs("Cannnot accpet a new client : ".$new_index);
$this->logs("Reason : ".$this->getSocketError($this->ssock));
$this->logs("Closed a new client : ".$new_index);
socket_close($csock);
}
else{
$json = json_decode($msg);
if(isset($json->user_id) && isset($json->user_type)){
if($this->sendMessage($csock, "success") === FALSE){
$this->logs("Fail to send a message : ".$json->user_id);
$this->logs("Reason : ".$this->getSocketError($csock));
socket_close($csock);
}
else{
$this->clients[$new_index]['csock'] = $csock;
$this->clients[$new_index]['user_id'] = $json->user_id;
$this->clients[$new_index]['user_type'] = $json->user_type;
$this->logs("New Client Connected : ".$new_index);
$this->logs("user_id : ".$this->clients[$new_index]['user_id']);
$this->logs("user_type : ".$this->clients[$new_index]['user_type']);
}
}
else{
$this->logs("illegal a new client : ".$new_index." or invalid json");
$this->logs("Closed a new client : ".$new_index);
socket_close($csock);
}
}
}
else $this->logs("Not resource type");
}
}
/**
* If $user_id param is exist in client list, then return the index of list
* @param $user_id
*
* @return index/FALSE
*/
public function searchReceiverIndex($user_id){
for($i = 0; $i < count($this->clients); $i++){
if($this->clients[$i]['user_id'] == $user_id) return $i;
}
return FALSE;
}
}
?>
run.socket.server.php
#!/usr/local/bin/php -q
<?php
require_once("socket.server.php");
ini_set('error_reporting', E_ALL ^ E_NOTICE);
ini_set('display_errors', 1);
// Set time limit to indefinite execution
set_time_limit (0);
$ss = new SocketServer();
/**
* Setting parameters for Log
*/
$ss->echoflg = TRUE; // Enable Debug Method with echo
$ss->fileurl = $_SERVER['DOCUMENT_ROOT']."/socket.server.logs.txt"; // Set the url for server logs
/**
* Now Starting Socket Server
*/
if($ss->initServer() === TRUE){
while(TRUE){
$ss->resetClientList();
$ss->acceptClient();
/**
* Repeatedly check a new message on client list,
* if cannot read then the client will be removed in client list.
*/
if(count($ss->clients) > 0){
foreach($ss->clients as $k=>$v){
if(($msg = $ss->readMessage($ss->clients[$k]['csock'])) === FALSE){
$ss->logs("Cannnot read a data from client : ".$ss->clients[$k]['user_id']);
$ss->logs("Reason : ".$ss->getSocketError($ss->clients[$k]['csock']));
$ss->logs("Close a client : ".$ss->clients[$k]['user_id']);
socket_close($ss->clients[$k]['csock']);
unset($ss->clients[$k]); // Remove from client list
}
else{
$json = json_decode($msg);
if(isset($json->receivers) && isset($json->messages)){
if(($receiverIndex = $ss->searchReceiverIndex($json->receivers)) === FALSE){
$ss->logs("The receiver is not exist on the client list");
}
else{
/**
* Create a JSON message
*/
$a = array();
$a['from'] = $ss->clients[$k]['user_id'];
$a['messages'] = $json->messages;
$json = json_encode($a, JSON_UNESCAPED_UNICODE);
if($ss->sendMessage($ss->clients[$receiverIndex]['csock'], $json) === FALSE)
$ss->logs("Cannot send a message to : ".$ss->clients[$receiverIndex]['user_id']);
}
}
}
}
}
sleep(1);
}
$ss->closeServerSocket();
}
else{
$ss->logs("Cannot Start Socket Server");
}
?>
您可以在浏览器上运行run.socket.server.php。然后它将无限循环。 并且,创建了DOCUMENT_ROOT / socket.server.logs.txt。请在socket.server.logs.txt文件中检查服务器是否已成功启动。
继续运行以下客户端文件:
socket.client.php
<?php
//The Client
error_reporting(E_ALL);
function logs($handle, $log){
$log = date("Y-m-d H:i:s")."\r\n".$log."\r\n\r\n";
fwrite($handle, $log);
}
$handle = fopen($_SERVER['DOCUMENT_ROOT']."/client.txt", "a+");
logs($handle, "============= STARTED ==============");
$address = "10.76.15.2";
$port = 6666;
/* Create a TCP/IP socket. */
$socket = socket_create(AF_INET, SOCK_STREAM, 0);
if ($socket === false) {
logs($handle, "socket_create() failed: reason: " . socket_strerror(socket_last_error()));
echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
} else {
logs($handle, "socket successfully created.\n");
echo "socket successfully created.\n";
}
logs($handle, "Attempting to connect to '$address' on port '$port'...");
echo "Attempting to connect to '$address' on port '$port'...";
$result = socket_connect($socket, $address, $port);
if ($result === false) {
logs($handle, "socket_connect() failed.\nReason: ($result) " . socket_strerror(socket_last_error($socket)));
echo "socket_connect() failed.\nReason: ($result) " . socket_strerror(socket_last_error($socket)) . "\n";
} else {
logs($handle, "successfully connected to $address.");
echo "successfully connected to $address.\n";
}
$a = array();
$a['user_id'] = "12345678901234567x";
$a['user_type'] = "9";
$json = json_encode($a, JSON_UNESCAPED_UNICODE);
$sent = socket_write($socket, $json."\n\r", strlen($json."\n\r"));
logs($handle, "Writing resutls: $sent");
$input = socket_read($socket, 2048);
logs($handle, "Response from server is: $input");
echo "Response from server is: $input\n";
//echo "Closing socket...";
//socket_close($socket);
//logs($handle, "============= FINISHED ==============");
?>
然后,您可以看到一些结果文本。
在浏览器上运行客户端文件后,请参阅socket.server.logs.txt
嗯,目前,客户端已连接但未断开连接。
顺便说一句,在服务器上,日志文件被记录为已断开连接。
所以我认为。
可能是我错过了检测客户端断开连接的时间?
我认为socket.server.php
readMessage()
功能运行不正常。
我怎么能正确地知道要断开连接?