Unix Sockets для IPC

  • Автор темы Автор темы x00xer
  • Дата начала Дата начала

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 окружения
 
Почему не долго ? ( я тут новенький, незнаю вероятно очевидные вещи для бывалых )
 
whirlwind
что ж там красивого?
именно из-за такой каши в коде и разобраться не может...
 
да? а мне показалось это я писал, когда меня попросили быстренько присоплить :)
 
Спасибо, исправил...
Давайте же разбираться! :-)

-~{}~ 16.04.09 15:26:

Автор оригинала: StUV
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:

про буфферизацию слышал?
 
Автор оригинала: 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 ? в мануале кстати по этому вопросу ссовсем мало информации и примеров тоже
 
ну наверное вернет пустую строку.

[m]socket_read[/m]

Замечание: socket_read() returns a zero length string ("") when there is no more data to read.
у тебя на тот момент уже все чилды будут завершены, значит если данные кончились, то больше им взяться будет неоткуда.
 
Спасибо, кстати вот еще момент, я думал что общение через Юникс сокет это тогда когда создатеся специальный файлик в /tpm/*.sock а тут как бы в тмп пусто (( и в связи с этим вопрос -
Как скрипт определяет что данные в сокете от именно этих детей ?

Я к примеру запускаю этот скрипт в цги режиме а значит через броузер к нему можно обратиться 100 раз а это 200 детей да и 200 образений к сокету ...
 
Ну тут уже каша пошла. Не получится с этим скриптом так. Все-таки почитать про ipc придется.
 
С удовольствием прочту, а где прочитать ? дайте ссылку пожалуйста.
Есть где нить хорошая проверенная дока ?
 
Хз. Я давно когда то писал статьи но у меня сайт щас не работает. Под пых врядли что то есть. Ищите примеры на сях и перле. По перлу могу посоветовать ISBN 5-8046-0094-X там все это есть.
 
Вот и я о чем .. если надо на ПХП сделать что то чуть серъезней чем просто сайт на Джумле .. то информации ооооОчень мало ((

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

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

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

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

-~{}~ 17.04.09 12:22:

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