📄 socket.php
字号:
<?php/*** Netlands World Server is the coordinator of the VR in the Netlands Project* Copyright (C) 2002 Ricard Pillosu* * This program is free software; you can redistribute it and/or* modify it under the terms of the GNU General Public License* as published by the Free Software Foundation; either version 2* of the License, or (at your option) any later version.* * This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the* GNU General Public License for more details.* * You should have received a copy of the GNU General Public License* along with this program; if not, write to the Free Software* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*//* vim: set expandtab tabstop=4 shiftwidth=4 *//*** Search if this socket is ready to read/write or error** @param socket resource * @param action string May be "read" or "write" or "error"*/function socket_ready($socket, $action = "read"){ if ((!is_resource($socket)) || (get_resource_type($socket) != "Socket")){ socket_close($socket); throw new exception("Bad socket", debug_backtrace(), $socket); return(FALSE); } $fdset[] = $socket; switch($action) { case "read": $n = socket_select($fdset, ($a = NULL), ($a = NULL), 0, 0); break; case "write": $n = socket_select(($a = NULL), $fdset, ($a = NULL), 0, 0); break; case "error": $n = socket_select(($a = NULL), ($a = NULL), $fdset, 0, 0); break; default: throw new exception("Bad action", debug_backtrace(), $action); return(FALSE); } if(!in_array($socket, $fdset)) { // Is not ready return(FALSE); } // Is ready return (TRUE);}/*** Returns last socket error** @param socket resource socket to look for errors*/function get_socket_error($socket){ // Filter arguments if ((!is_resource($socket)) || (get_resource_type($socket) != "Socket")) { throw new exception("Bad socket", debug_backtrace(), $socket); return(FALSE); } $error_number = socket_last_error($socket); $error_msg = socket_strerror($error_number); return("[$error_number] $error_msg");}/*** Open a socket on port** so simple** @server int where to attach* @port int where to attach */function open_socket($config){ if (!is_array($config)) { throw new exception("Bad argument config", debug_backtrace(), $config); return(FALSE); } $server = $config['server']; $port = $config['port']; // Create socket on port $socket = socket_create(AF_INET, SOCK_STREAM, 0); if($socket === FALSE) { $m = "Could not create socket"; throw new exception($m, debug_backtrace(), get_socket_error($socket)); return(FALSE); } // Link the socket to the address $state = socket_connect($socket, $server, $port); if ($state < 1) { $m = "Could not connect socket"; throw new exception($m, debug_backtrace(), get_socket_error($socket)); return (FALSE); } $state = socket_set_nonblock($socket); if (!$state) { $m = "Could not set socket non block"; throw new exception($m, debug_backtrace(), get_socket_error($socket)); return(FALSE); } $msg = "Connect with $server on port $port"; $msg.= " on socket $socket "; log_msg($msg, "socket"); return($socket);}/*** Open a listening socket on port** @param config array Indexed. Contains 'server', 'port', 'max_connections'*/function open_listening_socket($config){ if (!is_array($config)) { throw new exception("Bad argument config", debug_backtrace(), $config); return(FALSE); } $server = $config['server']; $port = $config['port']; $backlog = $config['max_connections']; // Create socket on port $protocol = getprotobyname("TCP"); $listening_socket = socket_create(AF_INET, SOCK_STREAM, $protocol); if ($listening_socket < 1) { //si el resource es negatiu, error $m = "Could not create listening socket"; throw new exception($m, debug_backtrace(), get_socket_error($listening_socket)); return(FALSE); } // Set socket reusable $state = socket_setopt($listening_socket, SOL_SOCKET, SO_REUSEADDR, 1); if ($state < 1) { $m = "Could not set option SO_REUSEADDR in socket"; throw new exception($m, debug_backtrace(), get_socket_error($listening_socket)); } // LINGER -- the way we send all remaining data to sockets or not $ling["l_onoff"] = 0; $ling["l_linger"] = 0; $state = socket_setopt($listening_socket, SOL_SOCKET, SO_LINGER, $ling); if ($state < 1) { $m = "Could not set option SO_LINGER in socket"; throw new exception($m, debug_backtrace(), get_socket_error($listening_socket)); } // Set socket non blocking $state = socket_set_nonblock($listening_socket); if ($state < 1) { $m = "Could not set option non-bloking in socket"; throw new exception($m, debug_backtrace(), get_socket_error($listening_socket)); } // Link the socket to the address $state = socket_bind($listening_socket, $server, $port); if ($state < 1) { $m = "Could not bind socket to $server:$port"; throw new exception($m, debug_backtrace(), get_socket_error($listening_socket)); } $state = socket_listen($listening_socket, $backlog); if ($state < 1) { $m = "Could not listen on socket"; throw new exception($m, debug_backtrace(), get_socket_error($listening_socket)); } $msg = "Listening for connections on $server:$port backlog ".$backlog; log_msg($msg, "socket"); return($listening_socket);}/*** Close all clients sockets*/function close_all_clients_sockets(&$connections){ foreach(array_keys($connections) as $key) { close_socket($connections[$key]); } return(TRUE);}/*** Close socket** @param connection object*/function close_socket(&$connection){ if(is_a($connection, "connection") !== TRUE) { $m = "bad argument connection"; throw new exception($m, debug_backtrace(), $connection); return(FALSE); } if(is_a($connection->user, "user") == TRUE) { global $users; $result = $users->del_user($connection->user); } // Msg client $answer = array("message" => "All good things come to an end"); $data = get_xml_from_array($answer, "quit"); write_data_to_socket($connection, $data); // Erase of $connections list if (!unset_connection_data($connection)) { return (FALSE); } // Close socket $state = socket_close($connection->socket); if ($state < 0) { $m = "Could not close socket"; throw new exception($m, debug_backtrace(), get_socket_error($listening_socket)); return(FALSE); } return(TRUE);}/*** Accepts and save new connections on listening socket** It will add a new entry in connections array** @param socket resource socket to check for new connections*/function accept_new_connections(&$connections, $socket){ // Filter arguments if ((!is_resource($socket)) || (get_resource_type($socket) != "Socket")){ $m = "bad argument socket"; throw new exception($m, debug_backtrace(), $socket); return(FALSE); } $n = socket_ready($socket); if ($n) { $new_link = @socket_accept($socket); if($new_link < 1) { $m = "could not accept connections on socket"; throw new exception($m, debug_backtrace(), get_socket_error($listening_socket)); return(FALSE); } // store client data $client_data = array(); socket_getpeername($new_link, $remote_ip, $remote_port); $remote_name = gethostbyaddr($remote_ip); $new_connection = &new connection(); $new_connection->socket = $new_link; $new_connection->remote_ip = $remote_ip; $new_connection->remote_name = $remote_name; $new_connection->remote_port = $remote_port; $new_connection->protocol_type = connection::P_FLASH; // add to clients array $connections[] = &$new_connection; $total = count(array_keys($connections)); $msg = "Connection number $total"; log_msg($msg,"game", $new_connection); $array= array("message" => "Welcome to Netlands PHP Server"); $data = get_xml_from_array($array, "welcome"); write_data_to_socket($new_connection, $data); } return(TRUE);}/*** Look for clients inputs** call a select() on all client sockets*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -