Unix Sockets для IPC

x00xer

Новичок
Unix Sockets для IPC

Здравствуйте, у меня есть срочная задача состоит она в следующем -
мне нужно параллельно выполнить пару задач
Т.е. скрипт запускается делает двух детей которые идут делать дело, а после того все сделали отдают отцу наделанное :).
вот код (с миру по нитке так сказать
PHP:
error_reporting(E_ALL & E_NOTICE);

class Task {

    protected $pid;
    protected $ppid;


    function __construct(){
    }


	
    function fork($socket){

	
        $pid = pcntl_fork();

        if ($pid == -1)
            throw new Exception ('fork error on Task object');
        elseif ($pid) {
            # we are in parent class
            $this->pid = $pid;
        } else{
            # we are is child
            $this->run($socket);
        }

    }

    function run(){
        $this->ppid = posix_getppid();
        $this->pid = posix_getpid();
    }


    # call when a task in finished (in parent)
    function finish(){
        // echo "task finished {$this->pid}\n";
    }

    function pid(){
        return $this->pid;
    }
}

class asd extends Task
{
	
	
	function __construct($what)
	{
	
	}
	
    function run($msgqueue){
        parent::run();
		
               $result = array("child2" => "asdzxcasd");
		if(socket_write($msgqueue, serialize($result), strlen(serialize($result))) === false)
            echo "socket_write() failed.   Reason: ".socket_strerror( socket_last_error($msgqueue)));
        exit(0);
    }

	


}

class qwe extends Task{
	
	function __construct()
	{
	}
	
    function run($msgqueue)
	{
		parent::run();
                $result = array('child1' => 'qweasd');
		if(socket_write($msgqueue, serialize($result), strlen(serialize($result))) === false)
		            throw new Exception("socket_write() failed.   Reason: ".socket_strerror( socket_last_error($msgqueue)));

        exit(0);
    }
}

class TaskManager{

    protected $pool;

    function __construct(){
        $this->pool = array();
    }

    function add_task($task){
        $this->pool[] = $task;
    }

    function run(){
		$data = array();
		
	
		$sockets = array();


		if (socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $sockets) === false)
               echo "socket_create_pair failed. Reason: ".socket_strerror(socket_last_error());

	
	
        foreach($this->pool as $task){
            $task->fork($sockets[0]);
        }

        while(1){
            $pid = pcntl_wait($extra);
            if($pid == -1)
                break;
        }


		
		if(($data = socket_read($sockets[1], 200000, PHP_BINARY_READ)) === false)
               {
			echo 'error!';
		} 
		return unserialize($data);
    }

    function finish_task($pid){
        if($task = $this->pid_to_task($pid))
           $task->finish();
		
    }

    function pid_to_task($pid){
        foreach($this->pool as $task){
            if($task->pid() == $pid)
                return $task;
        }
        return false;
    }
}

// start application
function main()
{
	

	$manager = new TaskManager(); // create task manager
	
      ...      
 
	$manager->add_task(new qwe());
	$manager->add_task(new asd());

	$data = $manager->run();
}


main();
В результате этого скрипта в $data = $manager->run(); Я получаю результат только одного детеныша
пробывал через System V IPC сообщение тоже самое получае только результат одного...

В какую сторону смотреть то ? Как решить проблему ?
Скрипт запускаю из консоли и CGI окружения
 

x00xer

Новичок
Почему не долго ? ( я тут новенький, незнаю вероятно очевидные вещи для бывалых )
 

StUV

Rotaredom
whirlwind
что ж там красивого?
именно из-за такой каши в коде и разобраться не может...
 

whirlwind

TDD infected, paranoid
да? а мне показалось это я писал, когда меня попросили быстренько присоплить :)
 

x00xer

Новичок
Спасибо, исправил...
Давайте же разбираться! :)

-~{}~ 16.04.09 15:26:

Автор оригинала: StUV
whirlwind
что ж там красивого?
именно из-за такой каши в коде и разобраться не может...
Я не хочу спорить о красоте данного кода, но был бы рад подсказке, если Вы видите, где моя ошибка ?
Спасибо.
 

whirlwind

TDD infected, paranoid
PHP:
        if(($data = socket_read($sockets[1], 200000, PHP_BINARY_READ)) === false)
               {
            echo 'error!';
        } 
        echo "a $data\n";
        if(($data = socket_read($sockets[1], 200000, PHP_BINARY_READ)) === false)
               {
            echo 'error!';
        } 
        echo "b $data\n";
        return unserialize($data);
-~{}~ 16.04.09 15:41:

про буфферизацию слышал?
 

x00xer

Новичок
Автор оригинала: whirlwind
PHP:
        if(($data = socket_read($sockets[1], 200000, PHP_BINARY_READ)) === false)
               {
            echo 'error!';
        } 
        echo "a $data\n";
        if(($data = socket_read($sockets[1], 200000, PHP_BINARY_READ)) === false)
               {
            echo 'error!';
        } 
        echo "b $data\n";
        return unserialize($data);
-~{}~ 16.04.09 15:41:

про буфферизацию слышал?
Спасибо тебе добрый ты человек
:D Честно говоря с сокетами ранее не работал, про буферы конечно слышал, но почему то надеялся что socket_read об этом сам позаботиться...
Может быть можно как то в цикле это сделать ?
типа
PHP:
while ( буфер не закончится ) { читать из него }
только вот как scoket_read сообщит о том что буфер пуст ?? вернет 0 ? в мануале кстати по этому вопросу ссовсем мало информации и примеров тоже
 

whirlwind

TDD infected, paranoid
ну наверное вернет пустую строку.

[m]socket_read[/m]

Замечание: socket_read() returns a zero length string ("") when there is no more data to read.
у тебя на тот момент уже все чилды будут завершены, значит если данные кончились, то больше им взяться будет неоткуда.
 

x00xer

Новичок
Спасибо, кстати вот еще момент, я думал что общение через Юникс сокет это тогда когда создатеся специальный файлик в /tpm/*.sock а тут как бы в тмп пусто (( и в связи с этим вопрос -
Как скрипт определяет что данные в сокете от именно этих детей ?

Я к примеру запускаю этот скрипт в цги режиме а значит через броузер к нему можно обратиться 100 раз а это 200 детей да и 200 образений к сокету ...
 

whirlwind

TDD infected, paranoid
Ну тут уже каша пошла. Не получится с этим скриптом так. Все-таки почитать про ipc придется.
 

x00xer

Новичок
С удовольствием прочту, а где прочитать ? дайте ссылку пожалуйста.
Есть где нить хорошая проверенная дока ?
 

whirlwind

TDD infected, paranoid
Хз. Я давно когда то писал статьи но у меня сайт щас не работает. Под пых врядли что то есть. Ищите примеры на сях и перле. По перлу могу посоветовать ISBN 5-8046-0094-X там все это есть.
 

x00xer

Новичок
Вот и я о чем .. если надо на ПХП сделать что то чуть серъезней чем просто сайт на Джумле .. то информации ооооОчень мало ((

По тому как работать с юникс сокетам в мане пару строчек, как сделать форки и как они делят между собой ресурсы в мане 1,5 строчки ..

все пришлось скребсти в мейл листах и в баг треке -)

Всем спасибо, буду искать..
 

whirlwind

TDD infected, paranoid
Автор оригинала: x00xer
Вот и я о чем .. если надо на ПХП сделать что то чуть серъезней чем просто сайт на Джумле .. то информации ооооОчень мало ((
Да ничего удивительного. Потому что

PHP is an HTML-embedded scripting language
Но некторые камрады с пеной у рта доказывают что демонов на пыхе писать можно. Ну можно, можно и ложкой траншею рыть, и тесаком делать хирургические операции. Насколько успешно - другой вопрос.
 

Alexandre

PHPПенсионер
Но некторые камрады с пеной у рта доказывают что демонов на пыхе писать можно.
можно но не нужно. Полтора года назад мне предложили написать кеширующего демона на пыхе.... после изучения задачи я объяснил, что такое нужно писать на сях, выучил си и написал своего первого демона. Пыховые демоны не для нагрузочных проектов иначе они сожрут всю память.

-~{}~ 17.04.09 12:22:

вот должна быть настольная книга http://www.books.ru/shop/books/503720
все объяснено просто и ясно
 
Сверху