Answer the question
In order to leave comments, you need to log in
Sockets. Sending messages from one user only to another, and not to everyone?
Good afternoon, tell me how you can get out of the situation when you need to send the information received from the client through the socket not to all connected to the socket, but only to one of them by its ID. Is there any way to distinguish between clients?
Below is the code I am torturing.
<?
error_reporting( E_ALL ); //Выводим все ошибки и предупреждения
set_time_limit( 100 ); //Время выполнения скрипта не ограничено
ob_implicit_flush(); //Включаем вывод без буферизации
$host = '0.0.0.0'; //host
$port = 8890; //port
$null = NULL; //null var
//Create TCP/IP sream socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
//reuseable port
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
//bind socket to specified host
socket_bind($socket, $host, $port);
//listen to port
socket_listen($socket);
//create & add listning socket to the list
$clients = array( $socket );
$clients_id = array();
//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";
echo "OUTPUT HEADERS:\r\n". $upgrade;
@socket_write( $client_conn, $upgrade, strlen($upgrade) );
}
//start endless loop, so that our script doesn't stop
while (true) {
//manage multipal connections
$changed = $clients;
//returns the socket resources in $changed array
socket_select( $changed, $null, $null, 0, 10 );
//check for new socket
if( in_array( $socket, $changed ) ) {
$socket_new = socket_accept( $socket ); //accpet new socket
$clients[] = $socket_new; //add socket to client array
$header = socket_read( $socket_new, 1024 ); //read data sent by the socket
echo "INPUT HEADERS:\r\n". $header ."\r\n";
perform_handshaking( $header, $socket_new, $host, $port ); //perform websocket handshake
//socket_getpeername($socket_new, $ip); //get ip address of connected socket
$response = mask( '//c' ); //prepare json data
send_message( $response ); //notify all users about new connection
//make room for new socket
$found_socket = array_search( $socket, $changed );
unset( $changed[$found_socket] );
}
//loop through all connected sockets
foreach( $changed as $changed_socket ) {
//check for any incomming data
while( socket_recv( $changed_socket, $buf, 1024, 0 ) >= 1 ) {
$received_text = unmask($buf); //unmask datas
$received_text = explode( '//', $received_text );
if( 'nw' == $received_text[1] ) {
}
//$response_text = mask( '//m//' );
//send_message($response_text); //send data
break 2; //exist this loop
}
$buf = @socket_read( $changed_socket, 1024, PHP_NORMAL_READ );
if( $buf === false ) { // check disconnected client
// remove client for $clients array
$found_socket = array_search($changed_socket, $clients);
//socket_getpeername($changed_socket, $ip);
unset($clients[$found_socket]);
//notify all users about disconnected connection
//$response = mask( '//connection_end//' );
//send_message($response);
}
}
}
// close the listening socket
socket_close($sock);
function send_message( $msg ) {
global $clients;
foreach( $clients as $changed_socket ) {
@socket_write( $changed_socket, $msg, strlen($msg) );
}
return true;
}
?>
Answer the question
In order to leave comments, you need to log in
Do the clients even know about each other's existence? There is no visible mechanism for naming clients and passing those names. That is, each client in this code will simply send messages to all sockets, even to its own.
As a name, you can send the index in the array assigned when connecting. But on the client there should be processing of these indexes.
In theory, it should turn out that each client will know about all or a group of sockets with which it will communicate: about adding new ones, about deleting closed ones. And here it will also be possible to send any request to one specific socket by its name. Naturally, the server must select sockets according to the names specified in the messages and write only to them.
Here some kind of "protocol" over the sockets suggests itself in order to distinguish between private and general messages, although some string condition is enough - it's to your taste.
Well, what do I see in the code:
here, apparently, personal and general messages should be separated. Then the next line can
Then take this element for the same index and do
But then suddenly there is no socket in the "clients" array by index?
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question