Java コースの設計とアドレス帳を行う準備をします。 C/Sアーキテクチャを採用。クライアントはJava FXとJavaを使用し、サーバーはphpを使用し、ソケット通信を使用します。
PHP でのソケット通信について話しましょう:
その前に、TCP/IP と UDP について話さなければなりません。インターネットの普及に伴い、多かれ少なかれこれらのプロトコルについて聞いたことがある人は多いと思いますが、具体的にはどのようなものなのでしょうか?
1. TCP/IP、UDPとは何ですか?
TCP/IP (伝送制御プロトコル/インターネット プロトコル) は、ワイド エリア ネットワーク (WAN) 用に設計された業界標準のプロトコル セットです。 TCP/IP プロトコル スイートには、トランスポート層、ネットワーク層、およびリンク層が含まれます。
UDP (User Data Protocol) は、TCP に相当するプロトコルです。これは、TCP/IP プロトコル スイートのメンバーです。図 上 上でそれらの関係を直観的に示してみましょう:
ここではソケットではありません、ソケットはどこですか?使用は何ですか?心配しないでください。次にソケットとそれらの関係を紹介しましょう。上と同じ写真です。
これで二人の関係が分かりました。では、ソケットとは一体何でしょうか?使用は何ですか?
2. ソケットとは何ですか?用途は何ですか?
ソケットは、アプリケーション層と TCP/IP プロトコルスイート間の通信のための中間ソフトウェア抽象化層です。 インターフェイスのセットです。デザイン モードでは、Socket は実際にはファサード モードであり、複雑な TCP/IP プロトコル ファミリを Socket インターフェイスの背後に隠し、ユーザーにとっては一連の単純なインターフェイスだけで済み、Socket は指定されたプロトコルに準拠するようにデータを編成できます。ソケットはカプセル化されたインターフェイスのセットであるため、それを使用して通信するにはどうすればよいでしょうか?具体的なプロセスは何ですか?電話のプロセスを詳しく説明します。まず第一に、私たちの通話は監視されなければなりませんね?そうでなければ、他の人から電話を受けることは絶対にありません。誰かが電話をかけてきたら、最初にその番号をダイヤルします。その番号がターゲットであり、唯一の番号です。ダイヤル後、電話が接続され、チャットが終了したら電話を切って、他の人がその番号に再度電話をかける必要があります。ソケットについても同様です。クライアントがソケットを作成して接続要求を開始すると、サーバーはまずソケットを確立し、情報の送信を開始します。送信が完了したらソケットを閉じます。もちろん、サーバーはクライアントへの接続要求をアクティブに開始して、通信を開始することもできます。これは、双方向通信を可能にする ajax とは異なります。下の写真を見てください:
サーバー側から始めましょう。サーバーはまずソケットを初期化し、次にポートにバインドし、ポートをリッスンし、accept を呼び出してブロックし、クライアントが接続するのを待ちます。このとき、クライアントがSocketを初期化してからサーバーに接続すると、接続に成功するとクライアントとサーバー間の接続が確立されます。クライアントがデータリクエストを送信し、サーバーがリクエストを受信して処理し、その後、応答データをクライアントに送信し、クライアントがデータを読み取り、最後に接続を終了します
3. 関連関数ソケットの:
socket_accept() はソケット接続を受け入れます
socket_bind() はソケットを IP アドレスとポートにバインドします
socket_clear_error() はソケットエラーまたは最後のエラーコードをクリアします
socket_close() はソケットリソースを閉じます
socket_connect() は 1 つのソケット接続を開始します
socket_create_listen() は、指定されたポートでリッスンするソケットを開きます
socket_create_pair() は、未分化のソケットのペアを配列に生成します
socket_create() は、ソケットを生成します。これは、ソケットのデータ構造を生成するのと同等です
socket_get_option() は、ソケットのオプションを取得します
socket_getpeername() リモートの同様のホストの IP アドレスを取得します
socket_getsockname() ローカル ソケットの IP アドレスを取得します
socket_iovec_add() 新しいベクトルを分散/集約配列に追加します
socket_iovec_alloc() この関数は、送信、受信、およびread iovec データ構造を書き込む
socket_iovec_delete() 割り当てられた iovec を削除する
socket_iovec_fetch() 指定された iovec リソースのデータを返す
socket_iovec_free() iovec リソースを解放する
socket_iovec_set() iovec データの新しい値を設定する
socket_last_error () を入手してくださいcurrent ソケットの最後のエラー コードです
socket_listen() は、指定されたソケットからのすべての接続をリッスンします
socket_read() は、指定された長さのデータを読み取ります
socket_readv() は、分散/集約配列からデータを読み取ります
socket_recv() は、ソケットからキャッシュへのデータ
socket_recvfrom() 指定されたソケットからのデータを受け取ります。指定されていない場合、現在のソケットがデフォルトになります
socket_recvmsg() iovec からメッセージを受信します
socket_select() 複数選択
socket_send() この関数はデータを次の宛先に送信します接続されたソケット
socket_sendmsg () ソケットにメッセージを送信します
socket_sendto() 指定されたアドレスのソケットにメッセージを送信します
socket_set_block() ソケットをブロックモードに設定します
socket_set_nonblock() ソケットを非ブロックモードに設定します
socket_set_option() ソケット オプションを設定します
socket_shutdown() この関数を使用すると、読み取り、書き込み、または指定されたソケットを閉じることができます
socket_strerror() 指定されたエラー番号を持つ詳細なエラーを返します
socket_write() ソケット キャッシュにデータを書き込みます
4. ソケット通信のデモ:
//服务器端:<br /><?php//确保在连接客户端时不会超时set_time_limit(0);$ip = '127.0.0.1';$port = 1935;/* +------------------------------- * @socket通信整个过程 +------------------------------- * @socket_create * @socket_bind * @socket_listen * @socket_accept * @socket_read * @socket_write * @socket_close +-------------------------------- */if(($sock = socket_create(AF_INET,SOCK_STREAM,SOL_TCP)) < 0) { echo "socket_create() 失败的原因是:".socket_strerror($sock)."\n";}if(($ret = socket_bind($sock,$ip,$port)) < 0) { echo "socket_bind() 失败的原因是:".socket_strerror($ret)."\n";}if(($ret = socket_listen($sock,4)) < 0) { echo "socket_listen() 失败的原因是:".socket_strerror($ret)."\n";}$count = 0;do { if (($msgsock = socket_accept($sock)) < 0) { echo "socket_accept() failed: reason: " . socket_strerror($msgsock) . "\n"; break; } else { //发到客户端 $msg ="测试成功!\n"; socket_write($msgsock, $msg, strlen($msg)); echo "测试成功了啊\n"; $buf = socket_read($msgsock,8192); $talkback = "收到的信息:$buf\n"; echo $talkback; if(++$count >= 5){ break; }; } socket_close($msgsock);} while (true);socket_close($sock);?>
//客户端<br /><?phperror_reporting(E_ALL);set_time_limit(0);$ip = "127.0.0.1";$port = 1935;/* +------------------------------- * @socket连接整个过程 +------------------------------- * @socket_create * @socket_connect * @socket_write * @socket_read * @socket_close +-------------------------------- */$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);if ($socket < 0) { echo "socket_create() failed: reason: " . socket_strerror($socket) . "\n";}else { echo "OK.\n";}echo "试图连接 '$ip' 端口 '$port'...\n";$result = socket_connect($socket, $ip, $port);if ($result < 0) { echo "socket_connect() failed.\nReason: ($result) " . socket_strerror($result) . "\n";}else { echo "连接OK\n";}$in = "Ho\r\n";$in .= "first blood\r\n";$out = '';if(!socket_write($socket, $in, strlen($in))) { echo "socket_write() failed: reason: " . socket_strerror($socket) . "\n";}else { echo "发送到服务器信息成功!\n"; echo "发送的内容为:<font color='red'>$in</font> <br>";}while($out = socket_read($socket, 8192)) { echo "接收服务器回传信息成功!\n"; echo "接受的内容为:",$out;}echo "关闭SOCKET...\n";socket_close($socket);echo "关闭OK\n";?>
注: 1) サーバーは CLI モード、つまりコマンドで実行する必要があります。ラインモード。 CGI (ブラウザ アクセス) を使用しないでください。php.exe が存在するディレクトリを見つけて、次のコード、PHP サーバー ファイルを実行します。
5. ソケットをクラスにカプセル化します:
//ServerSocket.class.php<br />//客户端socket操作类
<?php error_reporting(E_ALL); set_time_limit(0); class ServerSocket { private $server_host; //服务器IP private $server_port; //服务器端口 private $client_host; //客户端IP private $client_port; //客户端端口 private $create_socket=null; private $accept_socket=null; private $get_data=""; private $send_data=""; //够造函数 public function __construct($host,$port){ if(!extension_loaded("socket")){ exit("请先打开socket扩展!"); } if(empty($host)) exit("请输入目标主机IP!"); if(empty($port)) exit("请输入有效端口号!"); $this->server_host=$host; $this->server_port=$port; $this->CreateSocket(); } //创建一个socket并将其用来绑定监听端口 private function createSocket(){ if($this->create_socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)==false){ echo "socket_create() failed. reason:".socket_strerror(socket_last_error())."\n"; } if(socket_bind($this->create_socket,$this->server_host,$this->server_port)==false){ echo "socket_bind()failed. reason:".socket_strerror(socket_last_error($this->create_socket))."\n"; } if(socket_listen($this->create_socket,5)==false){ echo "socket_listen()failed. reason:".socket_strerror(socket_last_error($this->create_socket))."\n"; } } //向目标主机发起连接 public function connectClient(){ if(socket_getpeername($this->create_socket,$this->client_host,$this->client_port)==null){ echo "socket_getpeername()failed. reason:".socket_strerror(socket_last_error($this->create_socket))."\n"; } if(socket_connect($this->create_socket,$this->client_host,$this->client_port)==false){ echo "socket_connect()failed. reason:".socket_strerror(socket_last_error($this->create_socket))."\n"; } } //接受连接获取到一个socket资源,想客户端读取以及传输信息 public function wr(){ do{ //循环防止阻塞延迟 if($this->accept_socket=socket_accept($this->create_socket)==null){ echo "socket_accept()failed. reason:".socket_strerror(socket_last_error($this->create_socket))."\n"; break; } $this->get_data = socket_read($this->accept_socket, 8192); $this->send_data=$this->operateData($this->get_data); if (socket_write($this->accept_socket,$this->send_data, strlen($this->send_data))==false) { echo "socket_write() failed reason:" . socket_strerror(socket_last_error($this->accept_socket)) ."\n"; } socket_close($this->accept_socket); }while(true); } //数据处理 private function operateData(){ return ; } //关闭监听socket private function closeSocket(){ socket_close($this->createSocket); } //析构函数 public function __destruct(){ $this->closeSocket(); } }
//ClientSocket.class.php//客户端socke操作类class Socket { private $host;//连接socket的主机 private $port;//socket的端口号 private $error=array(); private $socket=null;//socket的连接标识 private $queryStr="";//发送的数据 public function __construct($host,$port) { if(!extension_loaded("sockets")){ exit("请打开socket扩展 "); } if(empty($host)) exit("请输入目标地址"); if(empty($port)) exit("请输入有效的端口号"); $this->host=$host; $this->port=$port; $this->CreateSocket();//创建连接 } //创建socket private function CreateSocket(){ !$this->socket&&$this->socket=socket_create(AF_INET, SOCK_STREAM, SOL_TCP);//创建socket $r=@socket_connect($this->socket,$this->host,$this->port); if($r){ return $r; }else{ $this->error[]=socket_last_error($this->socket); return false; } } //向socket服务器写入数据并读取 public function wr($contents){ $this->queryStr=""; $this->queryStr=$contents; !$this->socket&&$this->CreateSocket(); $contents=$this->fliterSendData($contents); $result=socket_write($this->socket,$contents,strlen($contents)); if(!intval($result)){ $this->error[]=socket_last_error($this->socket); return false; } $response=socket_read($this->socket,12048); if(false===$response){ $this->error[]=socket_last_error($this->socket); return false; } return $response; } //对发送的数据进行过滤 private function fliterSendData($contents){ //对写入的数据进行处理 return $contents; } //所有错误信息 public function getError(){ return $this->error; } //最后一次错误信息 public function getLastError(){ return $this->error(count($this->error)); } //获取最后一次发送的消息 public function getLastMsg(){ return $this->queryStr; } public function getHost(){ return $this->host; } public function getPort(){ return $this->port; } //关闭socket连接 private function close(){ $this->socket&&socket_close($this->socket);//关闭连接 $this->socket=null;//连接资源初始化 } public function __destruct(){ $this->close(); }}