我有一个PHP脚本,可以创建和运行websocket。
$wmdir=dirname(__FILE__);
$privdir=dirname(__DIR__);
/////////// ======== FUNCTIONS ========== /////////////////
function customError2($errno, $errstr, $errfile, $errline) {
$theerror= "Error [$errno] in $errfile on line $errline : $errstr ";
}
function fatalHandler() {
$error = error_get_last();
if($error) {
wm_onerror('FATAL: '.$error["type"].$error["message"].$error["file"].$error["line"] ) ;}
}
set_error_handler("customError2");
register_shutdown_function("fatalHandler");
function wmlog($log){
global $privdir;
$f=fopen($privdir.'/logs/SocketLog'.date("d_m_y").'.log','a');
fwrite($f, PHP_EOL.date("h:i:s").'LOG: '.$log);
fclose($f);
}
include_once($wmdir.'/settings.php');
include_once($wmdir.'/class/Core.php');
include_once($wmdir.'/ajax/intocf.php');
////////////// V A R S /////////////////
$host = 'myhost.net'; $port = $argv[1]; $wscode=$argv[2];
$uid=$argv[3] ; $cid=$argv[4]; $ctype=$argv[5];
$mid=$argv[6]; $null = NULL; $puid='u'.$uid;
$pwid=0; $uhere=1; $uherewas=time();
$a_ignored=array(); $a_pids=array(); $a_viab=array();
$a_viaa=array(); $a_bora=array(); $a_ka=array();
$a_si=array();
$q_cd="SELECT * FROM chats".$mid." WHERE c_id= $cid LIMIT 1";
$c_cd=new Core('wmc'); $c_cd->query($q_cd); $a_cd=$c_cd->row();
// S S L C E R T I F I C A T E ///
$ssl_cert = $wmdir.'/ssl/cert.pem'; $ssl_pass='wnet';
if(!$context = stream_context_create()){
wmlog("ERROR creating context") ;
}else{
wmlog("context created") ;
}
stream_context_set_option($context, 'ssl', 'local_cert', $ssl_cert);
stream_context_set_option($context, 'ssl', 'passphrase', $ssl_pass);
stream_context_set_option($context, 'ssl', 'allow_self_signed', false);
stream_context_set_option($context, 'ssl', 'verify_peer', true);
// create SOCKET //
if(!$socket = stream_socket_server('ssl://'.$host.':'.$port, $errno, $errstr, STREAM_SERVER_BIND|STREAM_SERVER_LISTEN, $context)){
wmlog("ERROR creating socket") ;
}else{
wmlog("socket created") ;
}
$clients = array($socket);//create & add listning socket to the list
$sk='';
foreach($clients as $k=>$v){
$sk.=$k.',';
}
$a_ictmp=array( 'chat_id'=>$cid, 'mid'=>$mid);
// LET DB KNOW that User is back ///
$a_ub=array('action'=>'ub', 'chat_id'=>$cid, 'bywho'=>'s', 'bywho_id'=>0, 'scope'=>'a', 'mid'=>$mid);
$a_msdb=intochat($a_ub); // LET DB KNOW THAT USER IS BACK
//// STARTING LOOP //////
while (true) {//manage multiple connections
$changed = $clients;
stream_select($changed, $null, $null, 0, 10);
///////// AD NEW SOCKET ///////
if (in_array($socket, $changed)) {//check for new socket
$sk='';
foreach($clients as $k=>$v){
$sk.=$k.',';
}
$socket_new = stream_socket_accept($socket);
$header = fread($socket_new, 1024);
$a_h=explode(PHP_EOL, $header);
$s_get=$a_h[0]; $a_header=array();
$a_pv=explode('_', $s_get); $pid=$a_pv[1].$a_pv[2];
$wscode=$a_pv[3]; $a_bora[$pid]=$a_pv[4];
if($a_pv[4]=='b'){
$a_viab[]=$pid;
}elseif($a_pv[4]=='a'){
$a_viaa[]=$pid;
}
$clients[$pid] = $socket_new;
perform_handshaking($header, $socket_new, $host, $port);//-
$peer = stream_socket_get_name($socket_new, true); //-
$found_socket = array_search($socket, $changed);//make room for new socket
unset($changed[$found_socket]);
///// authenticate person trying to make connection ///////
if(in_array($pid, $a_pids)){ // person already in a socket
wmlog('CODES: '.$a_pids[$pid].' | '.$wscode); //wmlog('Socket ACCEPTED');
if($a_pids[$pid]!=$wscode){unset($clients[$pid]) ;}
}else{ // person not in a sockets yet so check the code
$con=0;
if($a_pv[1]=='u'){// WIZARD connecting to socket
if($a_pv[2]==$uid && $a_pv[3]==$a_cd['c_wscode']){
wmlog('USER '.$uid.' CONNECTED '); $con=1;
}else{ unset($clients[$pid]) ; wmlog('USER NOT CONNECTED '); } // NOT allowing connection
}elseif($a_pv[1]=='w'){// WIZARD CONNECTING
$q_cp="SELECT ucode FROM users_d WHERE u_id = ".$a_pv[2].' LIMIT 1 ';
$c_cp=new Core('wmu'); $c_cp->query($q_cp); $a_wscode=$c_cp->row(); $wsc1=trim($a_wscode['ucode']);
if(!empty($a_wscode) && $wsc1==$a_pv[3] && !in_array($pid, $a_ignored)){
$con=1;
}else{ unset($clients[$pid]) ;
}elseif($a_pv[1]=='s'){ // SYSTEM connecting for maintanance etc
if($a_pv[3]==$wscode){ // system code is correct
$con=1;
}else{ unset($clients[$pid]) ; wmlog('SYSTEM NOT CONNECTED '); } //
}
if($con==1){$a_ka[$pid]=time(); $a_bora[$pid]=$a_pv[4]; $a_si[$pid]=array('bora'=>$a_pv[4], 'woru'=>$a_pv[1] ); }
}// EOF if person not in sockets yet
$sk=''; foreach($clients as $k=>$v){$sk.=$k.',';} ; wmlog('SOCKETS: '.$sk);
}// EOF checking new connection
//loop through all connected sockets
foreach ($changed as $key => $changed_socket) {
while(fread($changed_socket, $buf, 1024, 0) >= 1){ //-
wmlog('key: '.$key.' || BORA: '.$a_bora[$key].' || BEFORE UNMASK: '.$buf.' AFTER UNMAS: '.unmask($buf));
$received_text = unmask($buf); wmlog('RECEIVED TEXT: '.$received_text);
$afterunmasking=($a_bora[$key]=='b')? $buf : unmask($buf) ;
$o_msg = json_decode($afterunmasking);//unmask data AND json decode
// PUT MESSAGE TO DB ////
// a_intochat: action, chat_id, bywho, bywho_id, scope, towho, towho_id, data1, time, ctype
if(is_object($o_msg)){
$a_msg = get_object_vars($o_msg); // convert object to array
foreach($a_msg as $k=>$v){wmlog($k.' : '.$v);} // LOG the message
$a_msg['chat_id']=$cid; $a_msg['ctype']=$ctype; $a_msg['mid']=$mid; $a_msg['uid']=$uid;
$action=(isset($a_msg['action']))? $a_msg['action'] : 0 ;
//$operation=(isset($a_msg['operation']))? $a_msg['operation'] : 'ic';
if(isset($a_msg['method']) && $a_msg['method']=='intochat' ){
wmlog('O:INTOCHAT: '.$a_msg['bywho'].' | '.$a_msg['bywho_id'].' | '.$a_msg['action']);
if(isset($a_msg['bywho']) && isset($a_msg['bywho_id']) && isset($a_msg['action'])){
$t_pid=$a_msg['bywho'].$a_msg['bywho_id']; $a_ka[$t_pid]=time(); // set keepalive time for this person
$a_msdb=intochat($a_msg); // ADD MESSAGE TO DB AND GET MESSAGES TO SEND BACK
$j_msdb=json_encode($a_msdb); wmlog('MSDB: '.$j_msdb); // $j_encoded;
if($a_msg['action']=='d'){$ctype='d'; $pwid='w'.$a_msg['towho_id']; $wid=$a_msg['towho_id']; } /// chat dedicated
if($a_msg['action']=='i' && $a_msg['towho']=='w'){$a_ignored[]='w'.$a_msg['towho_id'];} /// wizard ignored
send_message2($a_msdb); // send data back to chaters
/// chat closed or completed
if($a_msg['action']=='c'){ $cid=0; wmlog('CLOSECOMPLETE'); closesocket($port); break 3; }
// EOF if message from chater
}
}
switch ($action) { // ic - intochat ; ka - keepalive ; ul - user loged of
case 'ul': // User loged off so letting all know and closing socket
$a_icul=array('action'=>'ul', 'chat_id'=>$cid, 'bywho'=>'s', 'bywho_id'=>0, 'scope'=>'a', 'mid'=>$mid);
$a_msdb=intochat($a_icul); // ADD MESSAGE TO DB AND GET MESSAGES TO SEND BACK
send_message2($a_msdb); // send data back to chaters
closesocket($port); wmlog('user left (loged off)');
break 4;
case 'al': // ALERT
break ;
case "ka": /// keep alive from person
$t_pid=$a_msg['bywho'].$a_msg['bywho_id']; $a_ka[$t_pid]=time(); break;
case 'ts': /// TEST
wmlog('testinG: '.$a_msg['t']); $response=json_encode(array('action'=>'ts','r1'=>1));
send_message($response, 0);
break;
default:
wmlog('action UNKNOWN: '.$action);
}
}
break 2; //exist this loop
}
$buf = fread($changed_socket, 1024, PHP_NORMAL_READ);//-
////////////// SOMEBODY D I S C O N N E T E D ///////////////////
if ($buf === false) { // check disconnected client
// remove client from $clients array
$found_socket = array_search($changed_socket, $clients);
unset($clients[$found_socket]); wmlog('DISCONNECTED: '.$found_socket);
if($found_socket==$puid){ // its a USER who is DISCONNETED
$a_icul=array('action'=>'ul', 'chat_id'=>$cid, 'bywho'=>'s', 'bywho_id'=>0, 'scope'=>'a', 'mid'=>$mid);
$a_msdb=intochat($a_icul);
send_message2($a_msdb); // send data back to chaters
closesocket($port); wmlog('user left (disconnected)');
break 2;
}elseif((strpos($found_socket, 'w') !== false)){ // WIZARD left
$a_wl=array('action'=>'wl', 'chd'=>$cid, 'bywho'=>'s', 'bywho_id'=>0, 'scope'=>'a', 'mid'=>$mid);
send_message($a_wl, 0);
}
}
}
}
fclose($socket); //-
function send_message($msg_b, $a_id=0, $notall=0){
$msg = mask($msg_b);
global $clients, $uid, $a_bora; $a_s=$clients; unset($a_s[0]);
if(!is_array($a_id) && $a_id==0){ wmlog('message sent to everybody'); // send message to everybody
if(is_array($notall)){ // filter sockets message not to be sent to
foreach($notall as $v){unset($a_s[$v]);} // check which
}
}elseif(!is_array($a_id) && $a_id!=0){ wmlog('Sending to single socket '.$a_id);// message to be sent to a single socket ($a_id)
$a_s=array($a_id=>$clients[$a_id]);
}else{ // send message to selected sockets
$a_s=array(); //socket_write($clients[$id],$msg,strlen($msg));
foreach($a_id as $id){ $a_s[$id]= $clients[$id]; }
}
foreach($a_s as $sid=>$soc){
wmlog('M to be Sent to '.$sid);
if($a_bora[$sid]=='a'){$msg=mask($msg_b);}else{$msg=$msg_b;} /// check if to mask or not to mask
if(strpos($sid,'s')===false){ wmlog('M Sent to '.$sid); // exclude 0 and system socket clients
fwrite($clients[$sid],$msg);//-
}
}
unset($a_s); return true;
} // EOF send_message F
function send_message2($a_msdb){ wmlog('F: send_message2');
global $clients, $uid, $ctype, $cid, $pwid, $a_bora; $a_not_all=array(); $a_s=$clients; unset($a_s[0]);
if(isset($a_msdb['some']) && is_array($a_msdb['some']) ){ // send message to some users
foreach($a_msdb['some'] as $k=>$v){ wmlog('SENDING TO '.$k.' : '.implode(' , ', $v));
if($a_bora[$k]=='a'){$msg = mask(json_encode($v));}else{$msg = json_encode($v);}
$a_not_all[]=$k;
if(isset($a_s[$k])){
fwrite($a_s[$k],$msg);
unset($a_s[$k]); }
}
}
if(isset($a_msdb['all']) && is_array($a_msdb['all']) ){ // send message to all other if needs be
foreach($a_s as $sid=>$soc){
if($a_bora[$sid]=='a'){$msg = mask(json_encode($a_msdb['all']));}else{$msg = json_encode($a_msdb['all']);}
fwrite($clients[$sid], $msg);//-
}
}
unset($a_s); return true;
}
//Unmask incoming framed message
function unmask($text) {
$length = ord($text[1]) & 127;
if($length == 126) { $masks = substr($text, 4, 4); $data = substr($text, 8);
}elseif($length == 127) { $masks = substr($text, 10, 4); $data = substr($text, 14);
}else{ $masks = substr($text, 2, 4); $data = substr($text, 6); }
$text = "";
for ($i = 0; $i < strlen($data); ++$i) { $text .= $data[$i] ^ $masks[$i%4]; }
return $text;
}
//Encode message for transfer to client.
function mask($text){
$b1 = 0x80 | (0x1 & 0x0f); $length = strlen($text);
if($length <= 125){ $header = pack('CC', $b1, $length); }
elseif($length > 125 && $length < 65536){ $header = pack('CCn', $b1, 126, $length); }
elseif($length >= 65536) { $header = pack('CCNN', $b1, 127, $length); }
return $header.$text; }
//handshake new client.
function perform_handshaking($receved_header,$client_conn, $host, $port){
$headers = array(); $lines = preg_split("/\r\n/", $receved_header);
foreach($lines as $line) {
$line = chop($line);
if(preg_match('/\A(\S+): (.*)\z/', $line, $matches)){ $headers[$matches[1]] = $matches[2]; }
}
$secKey = $headers['Sec-WebSocket-Key'];
$secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
//hand shaking header
$upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" . "Upgrade: websocket\r\n" . "Connection: Upgrade\r\n" .
"WebSocket-Origin: $host\r\n" . "WebSocket-Location: ws://$host:$port\r\n". "Sec-WebSocket-Accept:$secAccept\r\n\r\n";
//-socket_write($client_conn,$upgrade,strlen($upgrade));
fwrite($client_conn,$upgrade,strlen($upgrade));
}
function closesocket($port){
$q_rw="UPDATE wss SET ws_cid= 0 , ws_mid= 0 , ws_used= 0, wreleasetime= ".time()." WHERE wport= $port ";
$c_rw=new Core('wmc'); $c_rw->query($q_rw);
}
wmlog('SOCKET CLOSING - last line');
问题是,当客户端尝试连接到它时出现以下错误,它会失败:
&#34;第71行/opt/bitnami/apache2/mysite/socket.php中的错误[2]:stream_socket_accept():SSL操作失败,代码为1. OpenSSL错误消息:错误:14094418:SSL例程:ssl3_read_bytes:tlsv1提醒未知的ca&#34;
我用openssl创建了证书
感谢