Форум программистов, компьютерный форум, киберфорум
PHP
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.70/74: Рейтинг темы: голосов - 74, средняя оценка - 4.70
 Аватар для SanychBY
39 / 46 / 3
Регистрация: 04.06.2013
Сообщений: 1,532

Сокеты на PHP. Создание онлайн чата

28.12.2014, 21:14. Показов 14776. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток.
Недавно наткнулся на вот это http://php.net/manual/ru/book.sockets.php
И сразу стало интересно. Возможно ли на этом написать онлайн чат как на той же nodejs? Какие у него будут недостатки, а какие преимущества?
Можно ссылку на хорошие уроки касательно этого.
Спасибо.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
28.12.2014, 21:14
Ответы с готовыми решениями:

Ошибка в коде онлайн чата PHP
код кнопки Отправить Global $login; $Mess = c("Mess")->text; ...

Создание и перенос онлайн-чата на сервер
создал простенький чат по примеру с сайта разработчиков http://socket.io/get-started/chat/ на компутере работает как локальный сервер...

Создание wap чата на php
ищю людей знающих php!!!!

10
88 / 88 / 34
Регистрация: 22.05.2012
Сообщений: 404
28.12.2014, 23:09
Ну это не совсем то. Для хорошего чата и обмена сообщениями есть возможность юзать веб сокеты вот кратенький обзор - http://habrahabr.ru/post/79038/
Плюсы - При умелом подходе можно сделать отличнейший чат даже с возможностью передавать файлы, такой себе скайп в браузере ))
Недостатки - нужен хороший сервер с root доступом ...
Также веб сокеты реализованы в phpDaemon. Но это уже совсем другая история
0
 Аватар для SanychBY
39 / 46 / 3
Регистрация: 04.06.2013
Сообщений: 1,532
28.12.2014, 23:21  [ТС]
Цитата Сообщение от Programmer_ Посмотреть сообщение
http://habrahabr.ru/post/79038/
не холодно, не жарко. везде есть примеры с js, но хоть кто нить рассказал подробно как это пашет на php
Цитата Сообщение от Programmer_ Посмотреть сообщение
Плюсы - При умелом подходе можно сделать отличнейший чат даже с возможностью передавать файлы, такой себе скайп в браузере ))
как я понимаю, плюс в том, что мы долбим бд только в случае реальной отправки сообщения, а не проверки, отправили нам новое сообщение или нет, как бы было в случае чата на ajax. Это бесценно.
0
88 / 88 / 34
Регистрация: 22.05.2012
Сообщений: 404
28.12.2014, 23:50
Вот пример простенького чата -
index.php
HTML5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<!DOCTYPE html>
<html>
<head>
<meta charset='UTF-8' />
<style type="text/css">
<!--
.chat_wrapper {
    width: 500px;
    margin-right: auto;
    margin-left: auto;
    background: #CCCCCC;
    border: 1px solid #999999;
    padding: 10px;
    font: 12px 'lucida grande',tahoma,verdana,arial,sans-serif;
}
.chat_wrapper .message_box {
    background: #FFFFFF;
    height: 150px;
    overflow: auto;
    padding: 10px;
    border: 1px solid #999999;
}
.chat_wrapper .panel input{
    padding: 2px 2px 2px 5px;
}
.system_msg{color: #BDBDBD;font-style: italic;}
.user_name{font-weight:bold;}
.user_message{color: #88B6E0;}
-->
</style>
</head>
<body>  
<?php 
$colours = array('007AFF','FF7000','FF7000','15E25F','CFC700','CFC700','CF1100','CF00BE','F00');
$user_colour = array_rand($colours);
?>
 
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
 
<script language="javascript" type="text/javascript">  
$(document).ready(function(){
    //create a new WebSocket object.
    var wsUri = "ws://localhost:9000/demo/server.php";  
    websocket = new WebSocket(wsUri); 
    
    websocket.onopen = function(ev) { // connection is open 
        $('#message_box').append("<div class=\"system_msg\">Connected!</div>"); //notify user
    }
 
    $('#send-btn').click(function(){ //use clicks message send button   
        var mymessage = $('#message').val(); //get message text
        var myname = $('#name').val(); //get user name
        
        if(myname == ""){ //empty name?
            alert("Enter your Name please!");
            return;
        }
        if(mymessage == ""){ //emtpy message?
            alert("Enter Some message Please!");
            return;
        }
        
        //prepare json data
        var msg = {
        message: mymessage,
        name: myname,
        color : '<?php echo $colours[$user_colour]; ?>'
        };
        //convert and send data to server
        websocket.send(JSON.stringify(msg));
    });
    
    //#### Message received from server?
    websocket.onmessage = function(ev) {
        var msg = JSON.parse(ev.data); //PHP sends Json data
        var type = msg.type; //message type
        var umsg = msg.message; //message text
        var uname = msg.name; //user name
        var ucolor = msg.color; //color
 
        if(type == 'usermsg') 
        {
            $('#message_box').append("<div><span class=\"user_name\" style=\"color:#"+ucolor+"\">"+uname+"</span> : <span class=\"user_message\">"+umsg+"</span></div>");
        }
        if(type == 'system')
        {
            $('#message_box').append("<div class=\"system_msg\">"+umsg+"</div>");
        }
        
        $('#message').val(''); //reset text
    };
    
    websocket.onerror   = function(ev){$('#message_box').append("<div class=\"system_error\">Error Occurred - "+ev.data+"</div>");}; 
    websocket.onclose   = function(ev){$('#message_box').append("<div class=\"system_msg\">Connection Closed</div>");}; 
});
</script>
<div class="chat_wrapper">
<div class="message_box" id="message_box"></div>
<div class="panel">
<input type="text" name="name" id="name" placeholder="Your Name" maxlength="10" style="width:20%"  />
<input type="text" name="message" id="message" placeholder="Message" maxlength="80" style="width:60%" />
<button id="send-btn">Send</button>
</div>
</div>
 
</body>
</html>
server.php
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
<?php
$host = 'localhost'; //host
$port = '9000'; //port
$null = NULL; //null var
 
//Create TCP/IP sream socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
//reuseable port
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
 
//bind socket to specified host
socket_bind($socket, 0, $port);
 
//listen to port
socket_listen($socket);
 
//create & add listning socket to the list
$clients = array($socket);
 
//start endless loop, so that our script doesn't stop
while (true) {
    //manage multipal connections
    $changed = $clients;
    //returns the socket resources in $changed array
    socket_select($changed, $null, $null, 0, 10);
    
    //check for new socket
    if (in_array($socket, $changed)) {
        $socket_new = socket_accept($socket); //accpet new socket
        $clients[] = $socket_new; //add socket to client array
        
        $header = socket_read($socket_new, 1024); //read data sent by the socket
        perform_handshaking($header, $socket_new, $host, $port); //perform websocket handshake
        
        socket_getpeername($socket_new, $ip); //get ip address of connected socket
        $response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' connected'))); //prepare json data
        send_message($response); //notify all users about new connection
        
        //make room for new socket
        $found_socket = array_search($socket, $changed);
        unset($changed[$found_socket]);
    }
    
    //loop through all connected sockets
    foreach ($changed as $changed_socket) { 
        
        //check for any incomming data
        while(socket_recv($changed_socket, $buf, 1024, 0) >= 1)
        {
            $received_text = unmask($buf); //unmask data
            $tst_msg = json_decode($received_text); //json decode 
            $user_name = $tst_msg->name; //sender name
            $user_message = $tst_msg->message; //message text
            $user_color = $tst_msg->color; //color
            
            //prepare data to be sent to client
            $response_text = mask(json_encode(array('type'=>'usermsg', 'name'=>$user_name, 'message'=>$user_message, 'color'=>$user_color)));
            send_message($response_text); //send data
            break 2; //exist this loop
        }
        
        $buf = @socket_read($changed_socket, 1024, PHP_NORMAL_READ);
        if ($buf === false) { // check disconnected client
            // remove client for $clients array
            $found_socket = array_search($changed_socket, $clients);
            socket_getpeername($changed_socket, $ip);
            unset($clients[$found_socket]);
            
            //notify all users about disconnected connection
            $response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' disconnected')));
            send_message($response);
        }
    }
}
// close the listening socket
socket_close($sock);
 
function send_message($msg)
{
    global $clients;
    foreach($clients as $changed_socket)
    {
        @socket_write($changed_socket,$msg,strlen($msg));
    }
    return true;
}
 
 
//Unmask incoming framed message
function unmask($text) {
    $length = ord($text[1]) & 127;
    if($length == 126) {
        $masks = substr($text, 4, 4);
        $data = substr($text, 8);
    }
    elseif($length == 127) {
        $masks = substr($text, 10, 4);
        $data = substr($text, 14);
    }
    else {
        $masks = substr($text, 2, 4);
        $data = substr($text, 6);
    }
    $text = "";
    for ($i = 0; $i < strlen($data); ++$i) {
        $text .= $data[$i] ^ $masks[$i%4];
    }
    return $text;
}
 
//Encode message for transfer to client.
function mask($text)
{
    $b1 = 0x80 | (0x1 & 0x0f);
    $length = strlen($text);
    
    if($length <= 125)
        $header = pack('CC', $b1, $length);
    elseif($length > 125 && $length < 65536)
        $header = pack('CCn', $b1, 126, $length);
    elseif($length >= 65536)
        $header = pack('CCNN', $b1, 127, $length);
    return $header.$text;
}
 
//handshake new client.
function perform_handshaking($receved_header,$client_conn, $host, $port)
{
    $headers = array();
    $lines = preg_split("/\r\n/", $receved_header);
    foreach($lines as $line)
    {
        $line = chop($line);
        if(preg_match('/\A(\S+): (.*)\z/', $line, $matches))
        {
            $headers[$matches[1]] = $matches[2];
        }
    }
 
    $secKey = $headers['Sec-WebSocket-Key'];
    $secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
    //hand shaking header
    $upgrade  = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
    "Upgrade: websocket\r\n" .
    "Connection: Upgrade\r\n" .
    "WebSocket-Origin: $host\r\n" .
    "WebSocket-Location: ws://$host:$port/demo/shout.php\r\n".
    "Sec-WebSocket-Accept:$secAccept\r\n\r\n";
    socket_write($client_conn,$upgrade,strlen($upgrade));
}
$port - этот порт должен быть открыт.
По сути дела со стороны сервера это постоянно работающий скрипт while (true) ... Я думаю более подробного описания приводить нет смысла, все и так понятно

Добавлено через 11 минут
а, и да. Скрипт server.php должен быть запущен перед соединением с сокетом, т.е. ( самый простой способ это запустить его с консоли - php /path/to/myhost/server.php ) запускаем тогда можно уже и соединятся
1
 Аватар для SanychBY
39 / 46 / 3
Регистрация: 04.06.2013
Сообщений: 1,532
28.12.2014, 23:57  [ТС]
Цитата Сообщение от Programmer_ Посмотреть сообщение
а, и да. Скрипт server.php должен быть запущен перед соединением с сокетом, т.е. ( самый простой способ это запустить его с консоли - php /path/to/myhost/server.php ) запускаем тогда можно уже и соединятся
Его не запустит пользователь? У меня хостинг. Там такое не провернуть.

Добавлено через 53 секунды
Да и так с ходу весь код не разобрать.

Добавлено через 2 минуты
главная задача убрать нагрузку с бд
0
88 / 88 / 34
Регистрация: 22.05.2012
Сообщений: 404
29.12.2014, 00:01
Цитата Сообщение от Programmer_ Посмотреть сообщение
Недостатки - нужен хороший сервер с root доступом ...
тут хостинг не поможет, для того чтобы юзать нужен ВПС с рутом или же свой сервак

Добавлено через 1 минуту
Цитата Сообщение от SanychBY Посмотреть сообщение
главная задача убрать нагрузку с бд
Юзай мемкеш
0
 Аватар для SanychBY
39 / 46 / 3
Регистрация: 04.06.2013
Сообщений: 1,532
29.12.2014, 00:01  [ТС]
Цитата Сообщение от Programmer_ Посмотреть сообщение
тут хостинг не поможет, для того чтобы юзать нужен ВПС с рутом или же свой сервак
Хорошо, а можно ли как то провернуть это ajax только не дергать бд каждый раз?
0
88 / 88 / 34
Регистрация: 22.05.2012
Сообщений: 404
29.12.2014, 00:07
Ужеж писал
Цитата Сообщение от Programmer_ Посмотреть сообщение
Юзай мемкеш
0
 Аватар для SanychBY
39 / 46 / 3
Регистрация: 04.06.2013
Сообщений: 1,532
29.12.2014, 00:40  [ТС]
Это все весело, но как сделать на подобии "пользователь набирает сообщение"?
0
 Аватар для Kazachek
18 / 18 / 8
Регистрация: 03.11.2013
Сообщений: 405
06.01.2017, 08:11
Жаль что начатое не завершено((
0
 Аватар для edward_freedom
1569 / 1448 / 303
Регистрация: 01.10.2011
Сообщений: 2,636
08.01.2017, 15:25
Kazachek, Возьми и заверши
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
08.01.2017, 15:25
Помогаю со студенческими работами здесь

Создание чата (PHP,Ajax,JSON,MySql)
Привет,народ ! Уже день мучаюсь над этим (кстати,я-чайник в этой сфере). Хочу создать чат (регистрация,лог ин,выбор юзера,с кем хочется...

Сокеты. Написание чата
пишу чат. на сервере: IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 7281); serverSocket = new...

Передача файлов через сокеты для чата
Здравствуйте, проблема такая- чат на tclientsocket и tserversocket режим не блокирующий. Как организовать пересылку файла от одного клиента...

Алгоритм создания онлайн-чата
Всем привет. Я решил создать подобие онлайн-чата на С#. Клиентская часть почти готова. Теперь передо мной встал вопрос: как...

Установка онлайн чата на сайте
Привет, гуру прогинга! Посоветуйте такую вещь: Есть сайт, который пишет команда прогеров на CMS Битрикс, нужно на нем сделать онлайн чат,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru