Socket's, проблемы.

Artik

Новичок
Socket's, проблемы.

deamon.php
PHP:
<?
///////////////////////
$ip     = '127.0.0.1';
$port     = 9876;
///////////////////////

set_time_limit(0);

error_reporting (E_ALL);

for ($i=0;$i<50;$i++){
echo "<!-- -->";
}
flush();

echo "Go...<br>";
flush();

$sock = socket_create (AF_INET, SOCK_STREAM, 0);
$ret = socket_bind ($sock, $ip, $port);
$ret = socket_listen ($sock, 5);

while (1==1){
$msgsock = socket_accept($sock);
$read = socket_read($msgsock, 1024);
socket_write($msgsock, $read);
echo $read . "<br>";
flush();
}
?>
add.php
PHP:
<body onload="document.post.txt.focus();">
<form action="add.php" method=post name=post>
<input type="text" name="txt">
</form>
<?
global $txt;
if ($txt!=""){
///////////////////////
$ip         = '127.0.0.1';
$port       = '9876';
///////////////////////


$fp = fsockopen($ip, $port, $errno, $errstr, 10);
fputs($fp, $txt);
fclose($fp);
}
?>
Вот такое намудрил я, вначале запускаю deamon.php, потом открываю в другом окне add.php, пишу текст, он по сокетам передаеться и отображаеться в окне открытого демона. Демон пишет это не только в echo но и в socket_write.
Так вот, задача такая: как законектиться несколькими окнами к демону, и что б в каждом выводился текст когда я что то пишу. Это я хочу организовать на этой системе чат.
Пытался так:
PHP:
<?
///////////////////////
$ip         = '127.0.0.1';
$port         = 9876;
///////////////////////

set_time_limit(0);
error_reporting (E_ALL);
echo "Reading...<br>";
flush();

for ($i=0;$i<50;$i++){
echo "<!-- -->";
}
flush();

$fp = fsockopen($ip, $port, $errno, $errstr);
while (1==1){
echo fread($fp, 1024);
flush();
}
?>
Но тогда вообще демон зависает и даже в echo нечего не выдает.
Мне кажиться что можно устанавливать только одно сокет соединение, и если запустить второе, то первое зависает пока не закончиться второе.
Как поступить?
 

tony2001

TeaM PHPClub
>Мне кажиться что можно устанавливать только одно сокет соединение, и если
> запустить второе, то первое зависает пока не закончиться второе.
тебе правильно кажЕтся.
два клиента не могут использовать одно соединение.

[m]stream_select[/m]
 

Artik

Новичок
Не совсем получаеться...
Я так понял смысл в том что в файле deamon.php нужно сделать цыкл который будет проходиться ко всем открытым подключениям и каждое по очереди присоединять функцией stream_select (или socket_select ?).
Если не сложно можно на примере в моем скрипте?
Вообще я хочу организовать чат на демоне...
 

vadim

Guest
Artik
Для многопользовательского сокет сервера вам нужно понять как работает socket_select.
Есть два типа: блокирующие сокеты и неблокирующие.
На мой взгляд (как на взгляд не какого то супер пупер профессионала) блокирующий сокет намного удобней (то есть им легче управлять), чем неблокирующий.
Сокет с блокировкой "замораживает" на такое время выполнение скрипта, пока socket_select не запишет какие то изменения в переданные ему массивы
Изменения - это подсоединение новых клиентов или сообщения от этих клиентов или же отсоединение клиента

Всех клиентов мы держим в array-е, который и передаём функции socket_select

Если хотите, могу скинуть сюда работающий простой многопользовательский сервер (который я кстати слегка переделал из сервера, находящегося в комментариях к каокй то sоcket функции на php.net)
 

vadim

Guest
PHP:
<?
// don't timeout
set_time_limit(0);

define("IP","127.0.0.1");
define("PORT",11000);
$NULL=NULL;

$server=socket_create(AF_INET,SOCK_STREAM,0) or die(socket_strerror(socket_last_error()));

socket_bind($server,IP,PORT) or die(socket_strerror(socket_last_error()));

socket_listen($server) or die(socket_strerror(socket_last_error()));


$clients=array($server);

while(TRUE)
{
	$read=$clients;
	
	$num_changed_clients=socket_select($read,$NULL,$NULL,NULL);
	if($num_changed_clients<1) continue;

	if(in_array($server,$read))
	{
		$new_client=socket_accept($server);
		$clients[]=$new_client;
		echo "New Client ist here\n";
		socket_write($new_client,"Hallo\n",strlen("Hallo\n"));
		$key=array_search($server,$read);
		unset($read[$key]);
	}
	
	

	foreach($read as $k=>$read_sock)
	{
		$msg=@socket_read($read_sock,512);
		
		if($msg!==false) $msg=trim($msg);
		
		if($msg===false || $msg=="end")
		{
			$key=array_search($read_sock,$clients);
			unset($clients[$key]);
			echo "Client is out\n";
			continue;
		}		
		else 
		{
			echo "client said: ".$msg."\n";
			$msg="Server->".$msg."\n";
			socket_write($read_sock,$msg,strlen($msg));
		}
	}

}


socket_close($server) or die(socket_strerror(socket_last_error()));
?>
Соответственно клиент при соединении сначало должен считать приветствие сервера, потом послать какую нибудь строку и в конце концов получить эту же строку назад
 

phprus

Moderator
Команда форума

vadim

Guest
Да, только данный пример работает только на Линуксах (так как fork используется-или я не прав??) и там используются неблокирующие сокеты, что для новичках в сокет программировании сложней понять
 

phprus

Moderator
Команда форума
vadim
От fork'а там можно избавиться закомментировав его. Он не обязателен для работы.

А вообще есть еще класс Net_Server (http://pear.php.net/package/Net_Server) спецаально преднозначенный для создания серверов.

P.S. это мое 100-е сообщение
 

Artik

Новичок
Дело не в самом демоне, а то как можно из него считывать и записывать в него через веб интерфейс а не через telnet.
Не сильно у меня это получаеться оно напостой открывает и закрывает соединение, или я не понимаю...
 
Сверху