Hướng dẫn dùng so_reuseaddr trong PHP

Có một số cách để giao tiếp giữa Flex và PHP nhưng một trong những cách thú vị hơn là qua các socket. Giao tiếp ổ cắm cho phép các nhà phát triển tạo giao tiếp gần thời gian thực bằng cách đẩy thông tin trực tiếp đến máy khách. Trong bài viết này, bạn sẽ thấy những điều cơ bản về cách sử dụng PHP làm máy chủ ổ cắm và kết nối nó với ứng dụng Flex.

Ổ cắm là một cách thực tế và hiệu quả để gửi dữ liệu từ máy chủ đến máy khách. Trong mô hình HTTP truyền thống, máy khách gửi yêu cầu đến máy chủ, máy chủ xử lý nó, máy khách nhận được phản hồi và cuối cùng ngắt kết nối khỏi máy chủ. Để làm điều này, HTTP yêu cầu khách hàng gửi một lượng thông tin bổ sung đáng kể, bao gồm thời gian duy trì kết nối, thông tin bảo mật và quyền và thông tin xác định yêu cầu. Khi gửi nhiều đợt dữ liệu trong một khoảng thời gian ngắn, như bạn có thể làm với báo giá chứng khoán hoặc ứng dụng trò chuyện, ứng dụng của bạn sẽ phải kết nối lại nhiều lần và thực hiện nhiều lần trao đổi qua lại với máy chủ, gửi thêm tất cả thông tin mỗi lần để có được dữ liệu. Mỗi giao dịch có thể mất gấp đôi thời gian kể từ khi khách hàng gửi yêu cầu và chờ phản hồi đến. Đó có thể là vấn đề đối với các ứng dụng cần phản hồi tức thời hoặc gần thời gian thực. May mắn thay, có một giải pháp dễ dàng cho vấn đề này: ổ cắm.

Không giống như HTTP, khi bạn sử dụng socket, ứng dụng sẽ thực hiện một yêu cầu duy nhất đến máy chủ; máy chủ mở một kết nối và duy trì nó để nó có thể đẩy dữ liệu ra máy khách bất cứ khi nào nó muốn. Cả máy khách và máy chủ đều liên kết với một ổ cắm để chúng có thể lắng nghe mọi thay đổi về thông tin và cả máy khách và máy chủ đều có thể gửi thông tin qua ổ cắm đó. Điều đó có nghĩa là khách hàng sẽ nhận được bất kỳ dữ liệu nào được gửi bởi máy chủ qua một ổ cắm mà không phải đưa ra yêu cầu. Kết quả là bạn có thể giảm thời gian nhận dữ liệu xuống một nửa và ứng dụng của bạn có thể gửi và nhận dữ liệu đó trong thời gian gần.

Để sử dụng ổ cắm với Flash Player, bạn phải thực hiện một vài bước bổ sung. Vì lý do bảo mật, Flash Player yêu cầu tệp chính sách phải có trên máy chủ mà máy khách sẽ kết nối. Có một bài viết về Trung tâm phát triển Adobebao gồm một số lý do đằng sau yêu cầu này và các bước cần thiết để thực hiện nó một cách chi tiết. Trước khi Flash Player gửi yêu cầu ổ cắm ra, trước tiên, nó tạo một kết nối ổ cắm khác trên một cổng cụ thể (843) và sau đó mong đợi phản hồi là tệp chính sách chứa thông tin về ai được phép kết nối và trên đó cổng Flash Player có thể tạo kết nối . Bài viết Kết nối nhà phát triển ở trên giải thích những gì các tệp chính sách nên chứa. Các tập tin chính sách được sử dụng trong bài viết này là dưới đây; nó được lưu trong cùng thư mục với mã PHP của bạn dưới dạng flashpolicy.xml.


Trên máy chủ, điều đó có nghĩa là bạn phải lập trình cho hai trường hợp; người đầu tiên xử lý kết nối Flash Player để lấy tệp chính sách và lần thứ hai xử lý kết nối Flash Player để chia sẻ dữ liệu. Với mục đích của hướng dẫn này, tôi đã chia hai trường hợp đó thành các tệp riêng biệt.

Tôi sẽ trình bày mã PHP để cung cấp tệp chính sách trước.

Xử lý yêu cầu tệp chính sách

Trước tiên, bạn cần lấy nội dung của tệp flashpolicy.xml và sau đó thiết lập ổ cắm. Hàm socket_create có ba tham số cho phép bạn xác định chính xác giao thức nào sẽ sử dụng khi tạo ổ cắm.

Khi bạn đã tạo nó, bạn cần liên kết với một máy chủ và một cổng cụ thể. Trong trường hợp này bởi vì, Flash Player sẽ yêu cầu dữ liệu từ cổng 843, đó là cổng để sử dụng. Sau bước ràng buộc, mã lắng nghe trên ổ cắm bị ràng buộc cho bất kỳ dữ liệu nào có thể được gửi từ máy khách.

// Next we bind to a specfic host and port. In this case, the port is 843 because // we're listening for Flash Player's policy file request. if (!socket_bind($socket, 'localhost', 843)) { echo 'Unable to bind socket: '. socket_strerror(socket_last_error()) . PHP_EOL; } else { echo "Socket bound to port 843.\n"; } // Once we successfully bind to the host and port, we can start listening for requests // from the client. if (!socket_listen($socket,SOMAXCONN)) { echo 'Unable to listen on socket: ' . socket_strerror(socket_last_error()); } else { echo "Listening on the socket.\n"; }

Do đó, ổ cắm phải được thiết lập chính xác và bạn có thể bắt đầu gửi và nhận dữ liệu. Giao tiếp ổ cắm rất khác với mô hình đáp ứng yêu cầu mà bạn có thể quen thuộc, và kết quả là mã có vẻ phản trực giác. Không giống như một trang PHP thông thường tải trong trình duyệt khi trình duyệt yêu cầu, giao tiếp ổ cắm liên tục. Kết quả là bạn không bao giờ muốn hoàn thành "tải" trang. Để đạt được mục đích đó, phần còn lại của mã được đặt trong một trong khi vòng lặp mà tiếp tục chạy, chấp nhận bất kỳ kết nối mà đi theo. 

Trong đó , trong khi vòng lặp, bạn cần phải tạo một kết nối bằng cách chấp nhận bất cứ điều gì cố gắng để kết nối với ổ cắm. Nếu kết nối thành công, bạn có một đối tượng kết nối mà sau đó bạn có thể đọc hoặc ghi vào.

// Unlike a typical PHP page which runs and then finishes, we want to always be // looking for new connections. So we use an infinite loop that will accept connections // and then handle them. while(true) { $connection = @socket_accept($socket); if ($connection) { echo "Client $connection connected!\n"; } else { echo "Bad connection."; }

Nếu Flash Player kết nối thành công, thì điều đầu tiên nó ghi vào ổ cắm là yêu cầu đến máy chủ cho tệp chính sách. Để xử lý điều đó trên máy chủ, cần có một cuộc gọi đến phương thức socket_read để lấy dữ liệu được gửi từ máy khách để có thể xử lý nó. Nếu mã phía máy chủ nhận được chuỗi "" theo sau là ký tự null thì nó sẽ gửi dữ liệu từ tệp chính sách, nếu không, nó chỉ đơn giản là đóng kết nối.


// Read the data the client is sending and set it as the input variable. // If that variable is a policy file request then we serve up the policy // file. $input = socket_read($connection,1024); echo $input."\n"; if( $input == "\0") { echo "Policy file request\n"; } else { echo "Unknown request\n"; socket_close($connection); break; }

Cuối cùng, bạn cần gửi các tập tin chính sách yêu cầu Flash Player và sau đó thoát khỏi trong khi vòng lặp. Trong ví dụ này, tệp chính sách xác định chính sách mở rộng cho phép mọi người kết nối, nhưng thông thường bạn muốn giới hạn tên máy chủ và cổng để kiểm soát cách Flash Player có thể kết nối với máy chủ ổ cắm của bạn.


// Send the data from the policy file to the client by writing it to the // socket. socket_write($connection,$content,strlen($content)); socket_write($connection,"\0",strlen("\0")); socket_close($connection); }

Bây giờ bạn có mã máy chủ sẽ cho phép Flash Player kết nối với ổ cắm và yêu cầu tệp chính sách. Lưu tệp này dưới dạng socket_authentication.php. Chạy mã này khác với chạy mã trên một trang web. Bởi vì bạn đã tạo một vòng lặp vô hạn, bạn không muốn tải nó trong trình duyệt và khiến nó bị đảo lộn mãi mãi. Thay vào đó, bạn có thể sử dụng công cụ dòng lệnh PHP và chạy nó trong một thiết bị đầu cuối. Hãy chắc chắn rằng tệp nhị phân PHP được thêm vào PATH của bạn hoặc duyệt đến vị trí của nó trên máy của bạn. Sau đó, bạn có thể chạy ứng dụng bạn vừa tạo và hiển thị tất cả văn bản đến thiết bị đầu cuối. Nó sẽ chạy cho đến khi bạn giết nó. Bạn có thể phải chạy nó bằng lệnh sudo vì bạn đang cố nghe trên một ổ cắm thấp hơn 1024. Đây là thiết bị đầu cuối của tôi trông như thế nào khi tôi thực hiện lệnh:


RYAN-STEWARTs-MacBook-Pro:socket_demo rstewart$ sudo php socket_authentication.php Password: Socket created. Socket bound to port 843. Listening on the socket.

Xử lý các yêu cầu trên ổ cắm chính

Trước khi chuyển sang phía Flash Player, bạn sẽ cần thiết lập mã bạn muốn chạy sau khi bạn được sự chấp thuận từ tệp chính sách để gửi dữ liệu qua ổ cắm. Để thiết lập ổ cắm, sử dụng cùng một mã được sử dụng ở trên nhưng với một cổng khác (trong trường hợp này là cổng 1740).


Tất cả điều này sẽ trông quen thuộc từ ví dụ trước. Một điểm khác biệt chính là tôi đã đặt logic kết nối vào hàm riêng của nó được gọi là created_connection (), lấy tên máy chủ và cổng. Sự khác biệt khác là thay vì gửi thông tin tệp chính sách, nó gọi một hàm có tên send_data () sau khi kết nối được thiết lập thành công. Hàm send_data () này sẽ tạo ra một loạt các trích dẫn chứng khoán và gửi chúng đến máy khách bằng cách sử dụng cùng phương thức socket_write () được sử dụng trong ví dụ trước.


function send_data($connection) { echo $connection; // Create a number between 30 and 32 that will be our initial stock price. $stock_price = rand(30,32); while (true) { socket_write($connection,"$stock_price\n",strlen("$stock_price\n")); sleep(2); // Generate a random number that will represent how much our stock price // will change and then make that number a decimal and attach it to the // previous price. $stock_offset = rand(-50,50); $stock_price = $stock_price + ($stock_offset/100); echo "$stock_price\n"; } }

Lưu cái này dưới dạng socket_quotes.php trong thư mục bạn đã đặt socket_authentication.php. Chạy nó theo cùng một cách; bạn sẽ thấy đầu ra sau đây khi bạn chạy nó trong thiết bị đầu cuối của bạn:


RYAN-STEWARTs-MacBook-Pro:socket_demo rstewart$ php socket_quotes.php Socket created. Set options on socket. Socket bound to port 1740. Listening on the socket.

Trước khi bạn chuyển sang mã Flex, hãy đảm bảo cả hai tệp này đang chạy trong các cửa sổ đầu cuối riêng biệt. Khi Flash Player kết nối, đầu tiên nó sẽ chạy mã socket_authentication.php khi nó kiểm tra tệp chính sách và sau đó chạy mã trong socket_quotes.php để bắt đầu nhận dữ liệu.

Tạo ứng dụng Flex

Mở Flash Builder 4 và tạo một dự án Flex mới. Đặt loại máy chủ thành Không / Khác và sử dụng vị trí dự án mặc định (hoặc vị trí khác nếu bạn muốn). 

Bước đầu tiên là thêm bố cục và mã thành phần. Ứng dụng này sẽ là một công cụ theo dõi chứng khoán cơ bản hiển thị giá cổ phiếu mới nhất, danh sách giá cổ phiếu cũ và biểu đồ hiển thị giá cổ phiếu theo thời gian. Tất cả các thành phần sẽ có trong MXML.


Đoạn mã trên xác định hai nút, một nút sẽ tạo kết nối và nút khác đóng lại. Tiếp theo, nó xác định trường RichText sẽ hiển thị giá cổ phiếu hiện tại. Theo sau đó là danh sách và biểu đồ, cả hai sẽ sử dụng một mảng làm dataProvider. Trong Flex, bạn có thể liên kết dữ liệu với các thành phần bằng cách sử dụng ký hiệu {} ; khi dữ liệu đó thay đổi tất cả các thành phần trực quan bị ràng buộc với nó cũng được cập nhật. Trong trường hợp này, danh sách và biểu đồ được liên kết với một mảng, ArrayStockData , do đó mọi thay đổi được thực hiện cho mảng sẽ được hiển thị trong biểu đồ và danh sách. Do đó, bạn chỉ có thể cập nhật dữ liệu trong mảng và toàn bộ ứng dụng sẽ hiển thị dữ liệu mới.

Với các thành phần được tạo, bạn đã sẵn sàng để chuyển sang phần tập lệnh của ứng dụng. Đây là nơi bạn tạo kết nối ổ cắm và cũng xử lý mọi dữ liệu đến. Bạn sẽ bắt đầu bằng cách xác định mảng và ổ cắm và sau đó tạo trình xử lý nhấp cho nút Kết nối. Tất cả mã ActionScript 3 phải nằm trong khối , vì vậy hãy đặt mã lên trên các thành phần.


Thẻ [Bindable] phía trên định nghĩa mảng cho phép bạn liên kết các thành phần với dữ liệu đó. Khi nhấp vào nút Kết nối, btn_clickHandler () sẽ tạo kết nối ổ cắm. Tạo kết nối ổ cắm trong Flex khá dễ dàng. Chỉ cần tạo một thể hiện của lớp Socket và sau đó gọi phương thức connect () trên nó với một máy chủ và một cổng. Bạn sẽ muốn thiết lập trình lắng nghe sự kiện để thực hiện một số hành động khi nhiều thứ xảy ra trên ổ cắm. Tôi đã bao gồm một số dưới đây. Đối với các sự kiện lỗi tôi chỉ cần tìm ra lỗi để người dùng có thể thấy nó. Khi người dùng kết nối, onConnect () thay đổi nhãn trên nút Kết nối thành "Đã kết nối" và vô hiệu hóa nó. Hàm quan trọng nhất là onProTHEREvent (), được gọi khi nhận được dữ liệu ổ cắm. Hàm đó xử lý dữ liệu được gửi bởi máy chủ socket.

protected function onSecurityError(event:SecurityErrorEvent):void { Alert.show(event.text); } protected function onIOError(event:IOErrorEvent):void { Alert.show(event.text); } protected function onConnect(event:Event):void { btnConnected.label = "Connected"; btnConnected.enabled = false; } protected function onProgressEvent(event:ProgressEvent):void { var data:String = socket.readUTFBytes(socket.bytesAvailable); if(Number(data) < Number(lblPrice.text)) { lblPrice.setStyle("color","#ff0000"); } else { lblPrice.setStyle("color","#00ff00"); } lblPrice.text = data; var lastValue:Number = arrStockData.length ? arrStockData[0].currentValue : 0; arrStockData.addItemAt({currentValue:data,lastValue:lastValue},0); trace('data received'); } protected function btnQuit_clickHandler(event:MouseEvent):void { socket.close(); btnQuit.enabled = false; } ]]>

Hàm onProTHEREvent () chịu trách nhiệm cho một số tác vụ. Quan trọng nhất, nó gọi phương thức readUTFBytes () trên ổ cắm và lưu dữ liệu đó để nó có thể hoạt động với nó. Lớp Socket trong Flash Player hỗ trợ gửi dữ liệu văn bản hoặc dữ liệu nhị phân qua ổ cắm để bạn có thể sử dụng một trong một số phương thức "đọc" tùy thuộc vào loại dữ liệu bạn cần đọc. Khi nhận được dữ liệu mới, onProTHEREvent () lưu trữ giá trị trước đó dưới dạng lastValue (sử dụng 0 nếu đây là điểm dữ liệu đầu tiên). Với thông tin đó, nó thêm một đối tượng mới vào mảng, ghi lại currentValue cũng như lastValue. Điều này sẽ được sử dụng như một phần của dự án giao diện cho ItemRenderer trong Danh sách. Logic so sánh giá trị hiện tại với giá trị trước đó để xác định xem cổ phiếu đã tăng hay giảm. Nếu nó bị hỏng, phương thức setStyle () được gọi để chuyển báo giá chứng khoán thành màu đỏ và nếu nó tăng lên, nó được đặt thành màu xanh lá cây. Hàm cuối cùng, btnQuit_clickHandler (), được gọi khi nhấp vào nút Đóng. Nó gọi phương thức close () trên socket để ngắt kết nối nó.

Và đó là tất cả để có nó. Nếu hai ứng dụng ổ cắm của bạn đang chạy trong thiết bị đầu cuối, bạn có thể chạy ứng dụng này. Bạn nên bắt đầu thấy các báo giá chứng khoán gần thời gian thực được gửi đến ứng dụng của bạn và danh sách và biểu đồ sẽ tự động cập nhật.

Bạn có thể sử dụng một tính năng mới trong Flex 4 cho phép bạn dễ dàng tạo các ứng dụng trông tùy chỉnh hơn và đặt giao diện lên đó để làm cho nó trông giống một bảng điều khiển chứng khoán thực hơn:

Hướng dẫn dùng so_reuseaddr trong PHP

Bạn có thể lấy tất cả các tập tin ở đây . Bây giờ bạn sẽ có cách tốt để tạo các ứng dụng dựa trên ổ cắm của riêng bạn trong PHP và Flex.

6 hữu ích 0 bình luận 10k xem chia sẻ