質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
WebSocket

WebSocketとは双方向・全二重コミュニケーションのためのAPIでありプロトコルのことを指します。WebSocketはHTML5に密接に結びついており、多くのウェブブラウザの最新版に導入されています。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

MAMP

Mac 上で WordPress などの動的ページのサイトが作れるように環境を構築するフリーソフト

Q&A

解決済

1回答

1627閲覧

社内共有上のlocalhost(MAMP)でWebSocketを利用した場合、自分以外のクライアントがサーバー接続できない

maguzo

総合スコア57

WebSocket

WebSocketとは双方向・全二重コミュニケーションのためのAPIでありプロトコルのことを指します。WebSocketはHTML5に密接に結びついており、多くのウェブブラウザの最新版に導入されています。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

MAMP

Mac 上で WordPress などの動的ページのサイトが作れるように環境を構築するフリーソフト

0グッド

1クリップ

投稿2019/11/22 05:15

編集2019/11/22 05:18

社内サーバーにMAMPでチャットアプリができないかと考えWebSocket+MAMPで
当該記事を参考に実装してみました。

社内サーバーについてはM:の領域を割り当てて、そこに自分はリモートデスクトップ接続をしてアクセスし、MAMPやserver.phpを起動させております。

環境:
MAMP : 4.0.0.26869 ※MAMP for windows
OS : Microsoft Windows [Version 6.3.9600]
M:にアクセスするためのアドレス sharem

その結果、自分自身のlocal desktop(共有サーバーではない)の複数ブラウザでsharem/chat開いた場合にはサーバー接続に成功して、動作(コメントが反映される)することが確認できました。

一方で、同じネットワーク内の隣のBさんが同じアドレスでアクセスした場合にはサーバー接続に失敗してしまいます。
※因みにsharem/sample.htmlでecho"hello";のようなファイルを試しに開けると動作するので共有サーバーのMドライブ上のMAMPは適切に動作しております。

以下のコードでしめした、//hereの箇所にあるように
wsUriやhost portの問題なのかもしれませんが、
自分のローカルでは共有サーバー上のWebSocketが正しく動作するのに他のクライアントでうまく接続できない理由がわからずにご質問させて頂きました。

アドバイスを頂けると嬉しいです。
宜しくお願い申し上げます。

php

1<?php 2//index.php 3$colors = array('#007AFF','#FF7000','#FF7000','#15E25F','#CFC700','#CFC700','#CF1100','#CF00BE','#F00'); 4$color_pick = array_rand($colors); 5?> 6 7<!DOCTYPE html> 8<html> 9<head> 10<meta name="viewport" content="width=device-width, initial-scale=1"> 11<style type="text/css"> 12.chat-wrapper { 13 font: bold 11px/normal 'lucida grande', tahoma, verdana, arial, sans-serif; 14 background: #00a6bb; 15 padding: 20px; 16 margin: 20px auto; 17 box-shadow: 2px 2px 2px 0px #00000017; 18 max-width:700px; 19 min-width:500px; 20} 21#message-box { 22 width: 97%; 23 display: inline-block; 24 height: 300px; 25 background: #fff; 26 box-shadow: inset 0px 0px 2px #00000017; 27 overflow: auto; 28 padding: 10px; 29} 30.user-panel{ 31 margin-top: 10px; 32} 33input[type=text]{ 34 border: none; 35 padding: 5px 5px; 36 box-shadow: 2px 2px 2px #0000001c; 37} 38input[type=text]#name{ 39 width:20%; 40} 41input[type=text]#message{ 42 width:60%; 43} 44button#send-message { 45 border: none; 46 padding: 5px 15px; 47 background: #11e0fb; 48 box-shadow: 2px 2px 2px #0000001c; 49} 50</style> 51</head> 52<body> 53 54<div class="chat-wrapper"> 55<div id="message-box"></div> 56<div class="user-panel"> 57<input type="text" name="name" id="name" placeholder="お名前" maxlength="15" /> 58<input type="text" name="message" id="message" placeholder="メッセージを入力してください..." maxlength="100" /> 59<button id="send-message">Send</button> 60</div> 61</div> 62 63<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> 64<script language="javascript" type="text/javascript"> 65 //create a new WebSocket object. 66 var msgBox = $('#message-box'); 67 var wsUri = "ws://localhost:9000/chat/server.php";//here 68 websocket = new WebSocket(wsUri); 69 70 websocket.onopen = function(ev) { // connection is open 71 msgBox.append('<div class="system_msg" style="color:#bbbbbb">サーバー接続に成功です"!</div>'); //notify user 72 } 73 // Message received from server 74 websocket.onmessage = function(ev) { 75 var response = JSON.parse(ev.data); //PHP sends Json data 76 77 var res_type = response.type; //message type 78 var user_message = response.message; //message text 79 var user_name = response.name; //user name 80 var user_color = response.color; //color 81 82 switch(res_type){ 83 case 'usermsg': 84 msgBox.append('<div><span class="user_name" style="color:' + user_color + '">' + user_name + '</span> : <span class="user_message">' + user_message + '</span></div>'); 85 break; 86 case 'system': 87 msgBox.append('<div style="color:#bbbbbb">' + user_message + '</div>'); 88 break; 89 } 90 msgBox[0].scrollTop = msgBox[0].scrollHeight; //scroll message 91 92 }; 93 94 websocket.onerror = function(ev){ msgBox.append('<div class="system_error">Error Occurred - ' + ev.data + '</div>'); }; 95 websocket.onclose = function(ev){ msgBox.append('<div class="system_msg">Connection Closed</div>'); }; 96 97 //Message send button 98 $('#send-message').click(function(){ 99 send_message(); 100 }); 101 102 //User hits enter key 103 $( "#message" ).on( "keydown", function( event ) { 104 if(event.which==13){ 105 send_message(); 106 } 107 }); 108 109 //Send message 110 function send_message(){ 111 var message_input = $('#message'); //user message text 112 var name_input = $('#name'); //user name 113 114 if(message_input.val() == ""){ //empty name? 115 alert("Enter your Name please!"); 116 return; 117 } 118 if(message_input.val() == ""){ //emtpy message? 119 alert("Enter Some message Please!"); 120 return; 121 } 122 123 //prepare json data 124 var msg = { 125 message: message_input.val(), 126 name: name_input.val(), 127 color : '<?php echo $colors[$color_pick]; ?>' 128 }; 129 //convert and send data to server 130 websocket.send(JSON.stringify(msg)); 131 message_input.val(''); //reset message input 132 } 133</script> 134</body> 135</html> 136

php

1<?php 2//serever.php 3$host = 'localhost'; //host //here 4$port = '9000'; //port //here 5$null = NULL; //null var 6 7//Create TCP/IP sream socket 8$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); 9//reuseable port 10socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1); 11 12//bind socket to specified host 13socket_bind($socket, 0, $port); 14 15//listen to port 16socket_listen($socket); 17 18//create & add listning socket to the list 19$clients = array($socket); 20 21//start endless loop, so that our script doesn't stop 22while (true) { 23 //manage multipal connections 24 $changed = $clients; 25 //returns the socket resources in $changed array 26 socket_select($changed, $null, $null, 0, 10); 27 28 //check for new socket 29 if (in_array($socket, $changed)) { 30 $socket_new = socket_accept($socket); //accpet new socket 31 $clients[] = $socket_new; //add socket to client array 32 33 $header = socket_read($socket_new, 1024); //read data sent by the socket 34 perform_handshaking($header, $socket_new, $host, $port); //perform websocket handshake 35 36 socket_getpeername($socket_new, $ip); //get ip address of connected socket 37 $response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' connected'))); //prepare json data 38 send_message($response); //notify all users about new connection 39 40 //make room for new socket 41 $found_socket = array_search($socket, $changed); 42 unset($changed[$found_socket]); 43 } 44 45 //loop through all connected sockets 46 foreach ($changed as $changed_socket) { 47 48 //check for any incomming data 49 while(socket_recv($changed_socket, $buf, 1024, 0) >= 1) 50 { 51 $received_text = unmask($buf); //unmask data 52 $tst_msg = json_decode($received_text, true); //json decode 53 $user_name = $tst_msg['name']; //sender name 54 $user_message = $tst_msg['message']; //message text 55 $user_color = $tst_msg['color']; //color 56 57 //prepare data to be sent to client 58 $response_text = mask(json_encode(array('type'=>'usermsg', 'name'=>$user_name, 'message'=>$user_message, 'color'=>$user_color))); 59 send_message($response_text); //send data 60 break 2; //exist this loop 61 } 62 63 $buf = @socket_read($changed_socket, 1024, PHP_NORMAL_READ); 64 if ($buf === false) { // check disconnected client 65 // remove client for $clients array 66 $found_socket = array_search($changed_socket, $clients); 67 socket_getpeername($changed_socket, $ip); 68 unset($clients[$found_socket]); 69 70 //notify all users about disconnected connection 71 $response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' disconnected'))); 72 send_message($response); 73 } 74 } 75} 76// close the listening socket 77socket_close($socket); 78 79function send_message($msg) 80{ 81 global $clients; 82 foreach($clients as $changed_socket) 83 { 84 @socket_write($changed_socket,$msg,strlen($msg)); 85 } 86 return true; 87} 88 89 90//Unmask incoming framed message 91function unmask($text) { 92 $length = ord($text[1]) & 127; 93 if($length == 126) { 94 $masks = substr($text, 4, 4); 95 $data = substr($text, 8); 96 } 97 elseif($length == 127) { 98 $masks = substr($text, 10, 4); 99 $data = substr($text, 14); 100 } 101 else { 102 $masks = substr($text, 2, 4); 103 $data = substr($text, 6); 104 } 105 $text = ""; 106 for ($i = 0; $i < strlen($data); ++$i) { 107 $text .= $data[$i] ^ $masks[$i%4]; 108 } 109 return $text; 110} 111 112//Encode message for transfer to client. 113function mask($text) 114{ 115 $b1 = 0x80 | (0x1 & 0x0f); 116 $length = strlen($text); 117 118 if($length <= 125) 119 $header = pack('CC', $b1, $length); 120 elseif($length > 125 && $length < 65536) 121 $header = pack('CCn', $b1, 126, $length); 122 elseif($length >= 65536) 123 $header = pack('CCNN', $b1, 127, $length); 124 return $header.$text; 125} 126 127//handshake new client. 128function perform_handshaking($receved_header,$client_conn, $host, $port) 129{ 130 $headers = array(); 131 $lines = preg_split("/\r\n/", $receved_header); 132 foreach($lines as $line) 133 { 134 $line = chop($line); 135 if(preg_match('/\A(\S+): (.*)\z/', $line, $matches)) 136 { 137 $headers[$matches[1]] = $matches[2]; 138 } 139 } 140 141 $secKey = $headers['Sec-WebSocket-Key']; 142 $secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'))); 143 //hand shaking header 144 $upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" . 145 "Upgrade: websocket\r\n" . 146 "Connection: Upgrade\r\n" . 147 "WebSocket-Origin: $host\r\n" . 148 "WebSocket-Location: ws://$host:$port/demo/shout.php\r\n". 149 "Sec-WebSocket-Accept:$secAccept\r\n\r\n"; 150 socket_write($client_conn,$upgrade,strlen($upgrade)); 151} 152

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

localhostって自ホストのことだから、
適切なLAN上のIPアドレスをつけないといけないんじゃないですか?

イーサネットアダプターとかWi-FiとかのIPアドレスを
「ネットワークと共有センター」あたりから調べられますので。

投稿2019/11/22 05:43

編集2019/11/22 05:45
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maguzo

2019/11/22 06:03

コメントありがとうございます。 なるほど、と以下の様に var wsUri = "ws://localhost:9000/chat/server.php";//here var wsUri = "ws://xxx.xxx.x.xx:9000/chat/server.php";//here でIPアドレスでserver.phpにアクセスしようとしてもだめでした。。。因みにこのアドレスでも、自分のクライアントからは正しくは動作しています。
退会済みユーザー

退会済みユーザー

2019/11/22 06:17

で、IPアドレスの指定は必要なんだけど、サーバー役とクライアント役双方で、 ファイアウォールソフトがパケットを叩き落としていないかをチェックして、 遮断しているようなら設定変更をしましょう。
maguzo

2019/11/22 06:43

コメントありがとうございます "サーバー役とクライアント役双がファイアウォールソフトがパケットを叩き落としていないかをチェック"について、まだやり方はわからないのですが、頑張って調べてやってみます!
退会済みユーザー

退会済みユーザー

2019/11/22 07:56

セキュリティ対策ソフト、入れていなければ、Windowsファイアウォールにて、ソケット通信に使用するポート番号を遮断しないようにする、ということになります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問