Skip to content

Instantly share code, notes, and snippets.

@jerry80409
Created June 9, 2015 08:11
Show Gist options
  • Save jerry80409/cc9f12fda32496f44e22 to your computer and use it in GitHub Desktop.
Save jerry80409/cc9f12fda32496f44e22 to your computer and use it in GitHub Desktop.
PHP Socket Server
<?php
#error_reporting(E_ALL); // 顯示 所有的錯誤、警告
set_time_limit(0); //最大執行時間:無限制
ob_implicit_flush(); //立即清空
socket_clear_error();
/*******************************************************************************
* Create Socket
*******************************************************************************/
$commonProtocol = getprotobyname("tcp");
$resource = socket_create(AF_INET, SOCK_STREAM, $commonProtocol)
OR die('Socket_Create - '.socket_strerror(socket_last_error()).PHP_EOL);
# socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($resource, '127.0.0.1', 10001)
OR die('Socket_Bind - '.socket_strerror(socket_last_error()) .PHP_EOL);
// 5 - backlog指定同時能處理的最大連接要求,如果連接數目達此上限則client端將收到ECONNREFUSED的錯誤。
// echo SOMAXCONN; 128
socket_listen($resource, 5)
OR die('Socket_Listen - '.socket_strerror(socket_last_error()) .PHP_EOL);
/*******************************************************************************
* Accept any incoming connections to the server
*******************************************************************************/
echo '---------- Waitting For Clients ---------- ' .PHP_EOL;
//客戶端陣列
$clients = array($resource);
while (TRUE) {
// 阻塞模式
socket_set_block($resource);
// 建立副本
$read = $clients;
// 避免線程卡住, 等待 20 秒後逾時,
// socket_select - $read有動作或Timeout時會觸發一次執行
if(socket_select($read, $write=NULL, $except=NULL, 20) < 1){
// get a list of all the clients that have data to be read from
// if there are no clients with data, go to next iteration
echo 'Problem blocking socket_select?' .PHP_EOL;
continue;
}
// 確認 $resource 是否於 $read 陣列中
if(in_array($resource, $read)){
// 若 $resource 有接收到訊息, 回傳新的 socket resource, 並新增到 $clients 陣列中
// If socket has been made non-blocking using socket_set_blocking() or socket_set_nonblock(), FALSE will be returned.
$new_socket = socket_accept($resource);
$clients[] = $new_socket;
var_dump($clients); // debug
// timestamp
echo date("Y-m-d H:i:s") .PHP_EOL;
// welcome message
socket_write($new_socket, 'Welcome ! There are ' .(count($clients)-1) .' clients in the server ! '.PHP_EOL );
// get client ip
socket_getpeername($new_socket, $remote_ip);
echo 'Receive From - ' .$remote_ip .PHP_EOL;
}
foreach ($read as $read_sock) {
var_dump($read_sock); // debug
// read until newline or 1024 bytes
$data = @socket_read($read_sock, 1024);
// 收不到資料, 判斷為斷線
if($data == NULL){
// 若要設計成聊天室, 這邊需要緩衝 buffer
// remove client for $clients array
#$key = array_search($read_sock, $clients);
#unset($read[$key]);
#echo 'Client disconnected ! ' .PHP_EOL;
echo 'No Data' .PHP_EOL;
continue;
}
// blocking warring message
@socket_getpeername($read_socket, $remote_ip);
$data = trim($data);
echo 'Receive Data ( ' .$remote_ip .' ) - ' .$data .PHP_EOL;
// parser data
// insert database
/* //broadcast
if(! empty($data)) {
// send this to all the clients in the $clients array (except the first one, which is a listening socket)
foreach ($clients as $send_sock) {
if ($send_sock == $socket || $send_sock == $read_sock) {
// if its the listening sock or the client that we got the message from, go to the next one in the list
continue;
}
echo 'Receive Data - '.$data .PHP_EOL;
socket_write($send_sock, $data .PHP_EOL);
}
}*/
}
// 若有需要, 可以設計條件跳出while
// break;
} // end while loop
// close socket
socket_close($socket);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment