├── .gitattributes ├── .gitignore ├── ReadMe.md ├── index.php └── server.php /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | -------------------------------------------------------------------------------- /ReadMe.md: -------------------------------------------------------------------------------- 1 | Running Server : 2 | 3 | 1. Change host address in index.php and server.php 4 | 5 | 2. Go to your shell command-line interface 6 | 7 | 3. type: 8 | php -q c:\path\server.php 9 | 10 | 4. Using browser, navigate to index.php location to open chat page, have fun! 11 | 12 | @Tutorial : http://www.sanwebe.com/2013/05/chat-using-websocket-php-socket 13 | @License : http://opensource.org/licenses/MIT 14 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 50 | 51 | 52 | 53 |
54 |
55 |
56 | 57 | 58 | 59 |
60 |
61 | 62 | 63 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /server.php: -------------------------------------------------------------------------------- 1 | 'system', 'message'=>$ip.' connected'))); //prepare json data 37 | send_message($response); //notify all users about new connection 38 | 39 | //make room for new socket 40 | $found_socket = array_search($socket, $changed); 41 | unset($changed[$found_socket]); 42 | } 43 | 44 | //loop through all connected sockets 45 | foreach ($changed as $changed_socket) { 46 | 47 | //check for any incomming data 48 | while(socket_recv($changed_socket, $buf, 1024, 0) >= 1) 49 | { 50 | $received_text = unmask($buf); //unmask data 51 | $tst_msg = json_decode($received_text, true); //json decode 52 | $user_name = $tst_msg['name']; //sender name 53 | $user_message = $tst_msg['message']; //message text 54 | $user_color = $tst_msg['color']; //color 55 | 56 | //prepare data to be sent to client 57 | $response_text = mask(json_encode(array('type'=>'usermsg', 'name'=>$user_name, 'message'=>$user_message, 'color'=>$user_color))); 58 | send_message($response_text); //send data 59 | break 2; //exist this loop 60 | } 61 | 62 | $buf = @socket_read($changed_socket, 1024, PHP_NORMAL_READ); 63 | if ($buf === false) { // check disconnected client 64 | // remove client for $clients array 65 | $found_socket = array_search($changed_socket, $clients); 66 | socket_getpeername($changed_socket, $ip); 67 | unset($clients[$found_socket]); 68 | 69 | //notify all users about disconnected connection 70 | $response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' disconnected'))); 71 | send_message($response); 72 | } 73 | } 74 | } 75 | // close the listening socket 76 | socket_close($socket); 77 | 78 | function send_message($msg) 79 | { 80 | global $clients; 81 | foreach($clients as $changed_socket) 82 | { 83 | @socket_write($changed_socket,$msg,strlen($msg)); 84 | } 85 | return true; 86 | } 87 | 88 | 89 | //Unmask incoming framed message 90 | function unmask($text) { 91 | $length = ord($text[1]) & 127; 92 | if($length == 126) { 93 | $masks = substr($text, 4, 4); 94 | $data = substr($text, 8); 95 | } 96 | elseif($length == 127) { 97 | $masks = substr($text, 10, 4); 98 | $data = substr($text, 14); 99 | } 100 | else { 101 | $masks = substr($text, 2, 4); 102 | $data = substr($text, 6); 103 | } 104 | $text = ""; 105 | for ($i = 0; $i < strlen($data); ++$i) { 106 | $text .= $data[$i] ^ $masks[$i%4]; 107 | } 108 | return $text; 109 | } 110 | 111 | //Encode message for transfer to client. 112 | function mask($text) 113 | { 114 | $b1 = 0x80 | (0x1 & 0x0f); 115 | $length = strlen($text); 116 | 117 | if($length <= 125) 118 | $header = pack('CC', $b1, $length); 119 | elseif($length > 125 && $length < 65536) 120 | $header = pack('CCn', $b1, 126, $length); 121 | elseif($length >= 65536) 122 | $header = pack('CCNN', $b1, 127, $length); 123 | return $header.$text; 124 | } 125 | 126 | //handshake new client. 127 | function perform_handshaking($receved_header,$client_conn, $host, $port) 128 | { 129 | $headers = array(); 130 | $lines = preg_split("/\r\n/", $receved_header); 131 | foreach($lines as $line) 132 | { 133 | $line = chop($line); 134 | if(preg_match('/\A(\S+): (.*)\z/', $line, $matches)) 135 | { 136 | $headers[$matches[1]] = $matches[2]; 137 | } 138 | } 139 | 140 | $secKey = $headers['Sec-WebSocket-Key']; 141 | $secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'))); 142 | //hand shaking header 143 | $upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" . 144 | "Upgrade: websocket\r\n" . 145 | "Connection: Upgrade\r\n" . 146 | "WebSocket-Origin: $host\r\n" . 147 | "WebSocket-Location: ws://$host:$port/demo/shout.php\r\n". 148 | "Sec-WebSocket-Accept:$secAccept\r\n\r\n"; 149 | socket_write($client_conn,$upgrade,strlen($upgrade)); 150 | } 151 | --------------------------------------------------------------------------------