Задать вопрос
usdglander
@usdglander
Yipee-ki-yay

Как работать с сокетами в несколько потоков?

Добрый день!
Долго думал задавать вопрос или нет, так как он очень нубский, но в итоге решился.
Вообщем решил я освоить работу с сокетами и написать в качестве ознакомления простой чат. В качестве базы выбрал PHP (знаю то не лучший выбор, но вспоминать C++ и ставить студию не хотелось).
Работаю стандартно как написано в документации и примерах:
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
...
socket_bind($socket, $address, $port);
...
socket_listen($socket, 10);
...
  while (true) {
	$connect = socket_accept($socket);
	$result = socket_read($connect,1024);
	echo 'Common data: '.$result."\r\n";
	socket_write($connect,'You sending me: '.$result."\r\n");
	socket_shutdown($connect);
  }

При подключении к этому сокету на клиенте всё отрабатывается, но как только я пытаюсь подключить второго клиента, до того момента пока первое подключение не закрыто, то он висит и не может подключится, пока для первого не выполнится socket_shutdown($connect);
В связи с этим вопрос: Как мне организовать работу с несколькими подключениями одновременно? Иначе получается что каждый клиент, чтобы получить сообщения от других клиентов должен снова подключаться и запрашивать эти сообщения.
Пытаюсь создать несколько сокетов на одном и том же порту, но по понятным причинам мне этого сделать не дают.
Находил в инете пример именно на php, но ссылка на код оказалась битой.
Заранее спасибо всем ответившим.
  • Вопрос задан
  • 1421 просмотр
Подписаться 2 Оценить Комментировать
Решения вопроса 1
Существует 3 основных подхода.
1. То, что вы имеете ввиду - после accept() создавать отдельный поток на каждого лиента и обрабатывать пришедший коннект в нем.
2. Использовать один поток, переводить сокеты в неблокирующий режим и использовать select() или poll() / epol() / ... для обнаружения данных поступивших в сокет и их обработки
3. Использовать модель с несколькими worker'ами. Запускать несколько потоков-worker'ов работающих так же как в п.2, распределять входящие коннекты между ними. Обычно так пишут серверы для достаточно большой нагрузки.
Достаточно подробный ответ есть здесь: https://www.opennet.ru/base/faq/prog_faq.txt.html, см. "как писать сервера".
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
usdglander
@usdglander Автор вопроса, куратор тега PHP
Yipee-ki-yay
Поправьте меня если я не прав:
$clients = array();
$socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
socket_bind($socket,'127.0.0.1',$port);
socket_listen($socket);
socket_set_nonblock($socket);

while(true)
{
    if(($newc = socket_accept($socket)) !== false)
    {
        echo "Client $newc has connected\n";
        $clients[] = $newc;
    }
}

То есть мне нужно потом просто обходить массив $clients, ну и читать и отправлять как то данные, так?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы