GPS-logger/server1.php
Версия от 12:39, 11 февраля 2009; Gumanoed (обсуждение | вклад) (Новая: <pre> #!/usr/bin/php -q <?php // Simple PHP TCP server // ------------------------------------------------- // Простейший tcp-сервер на неблокирующих со...)
#!/usr/bin/php -q
<?php // Simple PHP TCP server
// -------------------------------------------------
// Простейший tcp-сервер на неблокирующих сокетах
// требуется наличие модулей sockets и pcntl
// -------------------------------------------------
// Инициализация сокета и начало его прослушивания
Function init_socket ($ip, $port)
{
// создаем новый сокет
if (($sockfd = socket_create (AF_INET, SOCK_STREAM, SOL_TCP)) < 0)
return -1;
// устанавливаем полезную опцию
socket_get_option ($sockfd, SOL_SOCKET, SO_REUSEADDR);
// привязываем сокет к IP и порту
if (socket_bind ($sockfd, $ip, $port) < 0)
return -1;
// начинаем слушать сокет
if (socket_listen ($sockfd) < 0)
return -1;
return $sockfd;
}
// Прием нового соединения
Function accept_connection ($ls)
{
GLOBAL $connections;
// принимаем новое соединение
$s = socket_accept ($ls);
socket_getpeername ($s, $addr);
// делаем сокет неблокирующим дабы процесс не вис на чтении из него
socket_set_nonblock ($s);
// записываем дескриптор сокета в массив. FIXME: количество соединений надо ограничивать
$connections[] = $s;
print "DEBUG: Connection from $addr accepted ". strftime ("%R:%S", time ()) ."\n";
}
$db_ident = NULL;
$db_descript = "host=localhost dbname=postgres port=5432 user=postgres password=123321";
Function db_write ($arr_dat)
{
GLOBAL $db_descript, $db_ident;
if (! $db_ident) {
if (! ($db_ident = pg_connect ($db_descript))) {
print "ERROR: pg_connect: Connection from $db_descript";
return -1;
}
}
$query = "INSERT INTO granit (stationid,pos_tstamp,londegrees,latdegrees,lonminutes,latminutes,speedknots,course,track) ".
sprintf ("VALUES (%d,%d, %d,%d,%d,%d, %d,%d,%d)", $arr_dat ['v2'], $arr_dat ['time'],
$arr_dat ['grad2'], $arr_dat ['grad1'], $arr_dat ['seck2'], $arr_dat ['seck1'],
$arr_dat ['xx1'], $arr_dat ['xx2'], $arr_dat ['track']);
// echo "$query\n";
return pg_query ($db_ident, $query);
}
// Чтение и обработка данных
Function read_socket ($rs)
{
$data = socket_read ($rs, 1024, PHP_BINARY_READ);
if ($data === false || $data == "") {
printf ("DEBUG: socket_read: %s\n", socket_strerror(socket_last_error()));
return -1;
}
// FIXME: сюда можно вставить вызов обработчика данных
$pmark = substr ($data, 0, 6);
if ("+RRCB~" == $pmark) {
$arr_dat = unpack ("v2v/Vtime/CE/CSP/C2grad/v2seck/C2xx/strack/C4", substr ($data, 6));
db_write ($arr_dat);
// квитация приема
$abuff = "BB+UGRC~". pack ("vVv", 6, $arr_dat ['time'], $arr_dat ['v2']) ."\r\n";
socket_write ($rs, $abuff);
} else if ("+DDAT~" == $pmark) {
$arr_dat = unpack ("v2v/Cblock/Cnform/Cnpack", substr ($data, 6));
print_r ($arr_dat);
$abuff = "+DDAT~";
$abuff = pack("vvCCv", $arr_dat['v1'], $arr_dat['v2'], $arr_dat['nform'], $arr_dat['block'], $arr_dat['npack'])."\r\n";
print (bin2hex ($abuff));
// socket_write ($rs, $abuff);
}
return 0;
}
// Закрытие соединения
Function close_connection ($rs)
{
GLOBAL $connections;
socket_getpeername ($rs, $addr);
// находим в массиве соединений нужное и закрываем его
$k = array_search ($rs, $connections);
unset ($connections[$k]);
socket_close ($rs);
print "DEBUG: Connection from $addr closed\n";
}
// Обработчик сигнала завершения работы
Function catch_interrupt ()
{
GLOBAL $alive;
print "DEBUG: Завершение работы\n";
$alive = 0;
}
// main ================================================================
//$ip = "127.0.0.1"; // слушаемый IP адрес
$ip = "89.109.54.20";
$port = "5555"; // слушаемый порт
$connections = array(); // массив активных соединений
$alive = 1; // спецфлаг
// разрешаем обработку сигналов и инсталируем обработчик сигнала SIGINT (Ctrl-C)
declare (ticks = 1);
pcntl_signal (SIGINT, "catch_interrupt");
if (($ls = init_socket ($ip, $port)) < 0) {
printf ("FATAL: %s\n", socket_strerror(socket_last_error()));
exit();
}
// основной цикл
// крутимся пока не поступит сигнал завершения работы
while ($alive) {
// определяем массив слушаемых и обрабатываемых сокетов
$reads = array ($ls); // первый дескриптор - слушаемый сокет
foreach ($connections as $c) { // остальные - активные соединения
$reads[] = $c;
}
// ждем доступности данных на сокетах
// $reads будет содержать _только_ дескрипторы, готовые для чтения
$n = socket_select ($reads, $write = NULL, $except = NULL, 0);
if ($n > 0) { // один или более сокетов содержат данные для чтения
if (in_array ($ls, $reads)) { // получен новый запрос на соединение?
$s = accept_connection ($ls); // принимаем новое соединение
$k = array_search ($ls, $reads);
unset ($reads[$k]); // удаляем дескриптор слушаемого сокета из массива
}
foreach ($reads as $rs) { // обрабатываем данные от сокетов (если таковые есть)
if (read_socket ($rs) < 0) { // производим чтение и обработку данных
close_connection ($rs); // при возникновении ошибки закрываем соединение
}
}
}
unset ($reads);
}
socket_close ($ls);
?>