◆ พื้นฐานซ็อกเก็ต
PHP ใช้ไลบรารีซ็อกเก็ตของ Berkley เพื่อสร้างการเชื่อมต่อ ซ็อกเก็ตไม่มีอะไรมากไปกว่าโครงสร้างข้อมูล คุณใช้โครงสร้างข้อมูลซ็อกเก็ตนี้เพื่อเริ่มเซสชันระหว่างไคลเอนต์และเซิร์ฟเวอร์ เซิร์ฟเวอร์นี้รับฟังและเตรียมสร้างเซสชันใหม่อยู่เสมอ เมื่อไคลเอ็นต์เชื่อมต่อกับเซิร์ฟเวอร์ ไคลเอ็นต์จะเปิดพอร์ตที่เซิร์ฟเวอร์กำลังฟังเซสชันอยู่ ในขณะนี้ เซิร์ฟเวอร์ยอมรับคำขอเชื่อมต่อของไคลเอนต์แล้วดำเนินการวนซ้ำ ตอนนี้ไคลเอนต์สามารถส่งข้อมูลไปยังเซิร์ฟเวอร์ และเซิร์ฟเวอร์สามารถส่งข้อมูลไปยังไคลเอนต์ได้
ในการสร้างซ็อกเก็ต คุณต้องมีตัวแปรสามตัว: โปรโตคอล ประเภทซ็อกเก็ต และประเภทโปรโตคอลสาธารณะ มีสามโปรโตคอลให้เลือกเมื่อสร้างซ็อกเก็ต อ่านต่อด้านล่างเพื่อรับเนื้อหาโปรโตคอลโดยละเอียด
การกำหนดประเภทโปรโตคอลสาธารณะเป็นองค์ประกอบสำคัญของการเชื่อมต่อ ในตารางด้านล่าง เราจะดูประเภทโปรโตคอลทั่วไป
ตารางที่ 1: ชื่อโปรโตคอล/คำอธิบายคงที่
AF_INET นี่คือโปรโตคอลที่ใช้โดยซ็อกเก็ตส่วนใหญ่ โดยใช้ TCP หรือ UDP สำหรับการส่งข้อมูล และใช้ในที่อยู่ IPv4
AF_INET6 คล้ายกับข้างต้น แต่ใช้สำหรับที่อยู่ IPv6
โปรโตคอลท้องถิ่น AF_UNIX ใช้บนระบบ Unix และ Linux โดยปกติจะใช้เมื่อไคลเอนต์และเซิร์ฟเวอร์อยู่บนเครื่องเดียวกัน ตารางที่ 2: ชื่อประเภทซ็อกเก็ต/คำอธิบายคงที่
SOCK_STREAM โปรโตคอลนี้เป็นการเชื่อมต่อแบบสตรีมไบต์ตามลำดับ เชื่อถือได้ รวมข้อมูล นี่คือประเภทซ็อกเก็ตที่ใช้บ่อยที่สุด ซ็อกเก็ตนี้ใช้ TCP สำหรับการส่งข้อมูล
SOCK_DGRAM โปรโตคอลนี้เป็นการโทรโอนย้ายแบบไม่มีการเชื่อมต่อและมีความยาวคงที่ โปรโตคอลนี้ไม่น่าเชื่อถือและใช้ UDP สำหรับการเชื่อมต่อ
SOCK_SEQPACKET โปรโตคอลนี้เป็นการเชื่อมต่อแบบสองบรรทัดที่เชื่อถือได้ซึ่งจะส่งแพ็กเก็ตข้อมูลที่มีความยาวคงที่สำหรับการส่งข้อมูล ต้องยอมรับแพ็กเก็ตนี้โดยสมบูรณ์ก่อนจึงจะสามารถอ่านได้
SOCK_RAW ประเภทซ็อกเก็ตนี้ให้การเข้าถึงเครือข่ายเดียว ประเภทซ็อกเก็ตนี้ใช้โปรโตคอลสาธารณะ ICMP (ping และ Traceroute ใช้โปรโตคอลนี้)
SOCK_RDM ประเภทนี้ไม่ค่อยได้ใช้และไม่ได้นำไปใช้กับระบบปฏิบัติการส่วนใหญ่ มีไว้เพื่อใช้โดย data link layer และไม่รับประกันลำดับแพ็กเก็ต ตารางที่ 3: ชื่อโปรโตคอลสาธารณะ/คำอธิบายคงที่
ICMP Internet Control Message Protocol ส่วนใหญ่ใช้กับเกตเวย์และโฮสต์เพื่อตรวจสอบสภาพเครือข่ายและรายงานข้อความแสดงข้อผิดพลาด
UDP User Datagram Protocol ซึ่งเป็นโปรโตคอลการส่งผ่านแบบไร้การเชื่อมต่อและไม่น่าเชื่อถือ
TCP Transmission Control Protocol ซึ่งเป็นโปรโตคอลสาธารณะที่เชื่อถือได้ที่ใช้กันมากที่สุด สามารถรับประกันได้ว่าแพ็กเก็ตข้อมูลสามารถเข้าถึงผู้รับได้ หากมีข้อผิดพลาดเกิดขึ้นระหว่างกระบวนการส่งข้อมูล ก็จะส่งแพ็กเก็ตข้อผิดพลาดอีกครั้ง
ตอนนี้คุณรู้องค์ประกอบสามประการที่สร้างซ็อกเก็ตแล้ว เราใช้ฟังก์ชัน socket_create() ใน PHP เพื่อสร้างซ็อกเก็ต ฟังก์ชัน socket_create() นี้ต้องการพารามิเตอร์สามตัว ได้แก่ โปรโตคอล ประเภทซ็อกเก็ต และโปรโตคอลสาธารณะ ฟังก์ชัน socket_create() จะส่งคืนประเภททรัพยากรที่มีซ็อกเก็ตหากทำงานสำเร็จ หากล้มเหลว จะคืนค่าเท็จ
ทรัพยากร socket_create (โปรโตคอล int, int socketType, int commonProtocol);
ตอนนี้คุณสร้างซ็อกเก็ตแล้วไงล่ะ? PHP มีฟังก์ชันหลายอย่างสำหรับจัดการซ็อกเก็ต คุณสามารถผูกซ็อกเก็ตเข้ากับ IP ฟังการสื่อสารของซ็อกเก็ต และยอมรับซ็อกเก็ตได้ ตอนนี้เรามาดูตัวอย่างเพื่อทำความเข้าใจว่าฟังก์ชันสร้าง ยอมรับ และรับฟังซ็อกเก็ตอย่างไร
<?php
$commonProtocol = getprotobyname("tcp");//ใช้ชื่อโปรโตคอลสาธารณะเพื่อรับประเภทโปรโตคอล
$socket = socket_create(AF_INET, SOCK_STREAM, $commonProtocol);//สร้างซ็อกเก็ตและส่งคืนอินสแตนซ์ของทรัพยากรซ็อกเก็ต
socket_bind($socket, 'localhost', 1337);//ผูกซ็อกเก็ตเข้ากับเครื่องคอมพิวเตอร์
socket_listen($socket);//ฟังการเชื่อมต่อซ็อกเก็ตขาเข้าทั้งหมด
// ฟังก์ชั่นซ็อกเก็ตเพิ่มเติมที่จะมา
-
ตัวอย่างข้างต้นสร้างฝั่งเซิร์ฟเวอร์ของคุณเอง บรรทัดแรกของตัวอย่าง
$commonProtocol = getprotobyname("tcp");
ใช้ชื่อโปรโตคอลสาธารณะเพื่อรับประเภทโปรโตคอล มีการใช้โปรโตคอลสาธารณะ TCP ที่นี่ หากคุณต้องการใช้โปรโตคอล UDP หรือ ICMP คุณควรเปลี่ยนพารามิเตอร์ของฟังก์ชัน getprotobyname() เป็น "udp" หรือ "icmp" อีกทางเลือกหนึ่งคือการระบุ SOL_TCP หรือ SOL_UDP ในฟังก์ชัน socket_create() แทนที่จะใช้ฟังก์ชัน getprotobyname()
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
บรรทัดที่สองของตัวอย่างจะสร้างซ็อกเก็ตและส่งกลับอินสแตนซ์ของทรัพยากรซ็อกเก็ต หลังจากที่คุณมีอินสแตนซ์ของทรัพยากรซ็อกเก็ตแล้ว คุณต้องผูกซ็อกเก็ตเข้ากับที่อยู่ IP และพอร์ต
socket_bind($socket, 'localhost', 1337);
ที่นี่คุณผูกซ็อกเก็ตกับคอมพิวเตอร์ในระบบ (127.0.0.1) และผูกซ็อกเก็ตเข้ากับพอร์ต 1337 ของคุณ จากนั้นคุณจะต้องฟังการเชื่อมต่อซ็อกเก็ตขาเข้าทั้งหมด
socket_listen($ซ็อกเก็ต);
หลังจากบรรทัดที่สี่ คุณจะต้องเข้าใจฟังก์ชันซ็อกเก็ตทั้งหมดและการใช้งาน
ตารางที่ 4: คำอธิบายชื่อฟังก์ชันฟังก์ชันซ็อกเก็ต
socket_accept() ยอมรับการเชื่อมต่อซ็อกเก็ต
socket_bind() ผูกซ็อกเก็ตกับที่อยู่ IP และพอร์ต
socket_clear_error() ล้างข้อผิดพลาดของซ็อกเก็ตหรือรหัสข้อผิดพลาดล่าสุด
socket_close() ปิดทรัพยากรซ็อกเก็ต
socket_connect() เริ่มการเชื่อมต่อซ็อกเก็ต
socket_create_listen() เปิดซ็อกเก็ตที่ฟังบนพอร์ตที่ระบุ
socket_create_pair() สร้างคู่ของซ็อกเก็ตที่แยกไม่ออกลงในอาร์เรย์
socket_create() สร้างซ็อกเก็ตซึ่งเทียบเท่ากับการสร้างโครงสร้างข้อมูลซ็อกเก็ต
socket_get_option() รับตัวเลือกซ็อกเก็ต
socket_getpeername() รับที่อยู่ IP ของโฮสต์ที่คล้ายกันระยะไกล
socket_getsockname() รับที่อยู่ IP ของซ็อกเก็ตในเครื่อง
socket_iovec_add() เพิ่มเวกเตอร์ใหม่ให้กับอาร์เรย์กระจาย/รวม
socket_iovec_alloc() ฟังก์ชันนี้สร้างโครงสร้างข้อมูล iovec ที่สามารถส่ง รับ อ่าน และเขียน
socket_iovec_delete() ลบ iovec ที่จัดสรรไว้
socket_iovec_fetch() ส่งคืนข้อมูลของทรัพยากร iovec ที่ระบุ
socket_iovec_free() เผยแพร่ทรัพยากร iovec
socket_iovec_set() ตั้งค่าใหม่ของข้อมูล iovec
socket_last_error() รับรหัสข้อผิดพลาดล่าสุดของซ็อกเก็ตปัจจุบัน
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() เขียนข้อมูลลงในซ็อกเก็ตแคช
socket_writev() เขียนข้อมูลลงในอาร์เรย์ที่กระจัดกระจาย/รวม ฟังก์ชันข้างต้นทั้งหมดเกี่ยวข้องกับซ็อกเก็ตใน PHP หากต้องการใช้ฟังก์ชันเหล่านี้ คุณต้องเปิดซ็อกเก็ตของคุณ หากคุณยังไม่ได้เปิด โปรดแก้ไขไฟล์ php.ini และลบออก ความคิดเห็นต่อไปนี้ก่อนบรรทัดนี้:
ส่วนขยาย=php_sockets.dll
หากคุณไม่สามารถลบความคิดเห็นได้ ให้ใช้โค้ดต่อไปนี้เพื่อโหลดไลบรารีส่วนขยาย:
<?php
ถ้า (!extension_loaded('ซ็อกเก็ต')) {
ถ้า (strtoupper (substr (PHP_OS, 3)) == “ชนะ”) {
dl('php_sockets.dll');
}อื่น{
dl('sockets.so');
-
-
-
หากคุณไม่ทราบว่าซ็อกเก็ตของคุณเปิดอยู่หรือไม่ คุณสามารถใช้ฟังก์ชัน phpinfo() เพื่อตรวจสอบว่าซ็อกเก็ตเปิดอยู่หรือไม่ คุณสามารถตรวจสอบว่าซ็อกเก็ตเปิดอยู่หรือไม่โดยตรวจสอบข้อมูล phpinfo
ดูข้อมูลของ phpinfo() เกี่ยวกับซ็อกเก็ต ◆ สร้างเซิร์ฟเวอร์ ตอนนี้เรามาปรับปรุงตัวอย่างแรกกันดีกว่า คุณต้องฟังซ็อกเก็ตเฉพาะและจัดการการเชื่อมต่อของผู้ใช้
<?php
$commonProtocol = getprotobyname("tcp");
$socket = socket_create(AF_INET, SOCK_STREAM, $commonProtocol);
socket_bind($socket, 'localhost', 1337);
socket_listen($ซ็อกเก็ต);
//ยอมรับการเชื่อมต่อขาเข้าไปยังเซิร์ฟเวอร์
$การเชื่อมต่อ = socket_accept($socket);
ถ้า($การเชื่อมต่อ){
socket_write($connection, "คุณได้เชื่อมต่อกับซ็อกเก็ตแล้ว...nr");
-
-
คุณควรใช้พรอมต์คำสั่งเพื่อเรียกใช้ตัวอย่างนี้ เหตุผลก็คือเนื่องจากเซิร์ฟเวอร์จะถูกสร้างขึ้นที่นี่ ไม่ใช่เว็บเพจ หากคุณพยายามเรียกใช้สคริปต์นี้โดยใช้เว็บเบราว์เซอร์ มีโอกาสที่ดีที่สคริปต์จะเกินขีดจำกัด 30 วินาที คุณสามารถใช้โค้ดด้านล่างเพื่อตั้งค่ารันไทม์แบบไม่จำกัดได้ แต่ขอแนะนำให้ใช้พรอมต์คำสั่งเพื่อรัน
set_time_limit (0);
เพียงทดสอบสคริปต์นี้ในพร้อมท์คำสั่งของคุณ:
ตัวอย่าง Php.exe01_server.php
หากคุณไม่ได้กำหนดเส้นทางไปยังล่าม php ในตัวแปรสภาพแวดล้อมของระบบ คุณจะต้องระบุเส้นทางไปยัง php.exe เมื่อคุณรันเซิร์ฟเวอร์ คุณสามารถทดสอบเซิร์ฟเวอร์ได้โดยการเชื่อมต่อกับพอร์ต 1337 ผ่านทาง telnet
มีปัญหาสามประการกับฝั่งเซิร์ฟเวอร์ด้านบน: 1. ไม่สามารถยอมรับการเชื่อมต่อหลายรายการได้ 2. ดำเนินการเพียงคำสั่งเดียวเท่านั้น 3. คุณไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์นี้ผ่านเว็บเบราว์เซอร์ได้
ปัญหาแรกนี้แก้ไขได้ง่ายกว่าคุณสามารถใช้แอปพลิเคชันเชื่อมต่อกับเซิร์ฟเวอร์ทุกครั้ง แต่ปัญหาต่อมาคือคุณต้องใช้เว็บเพจในการเชื่อมต่อกับเซิร์ฟเวอร์ซึ่งทำได้ยากกว่า คุณสามารถให้เซิร์ฟเวอร์ของคุณยอมรับการเชื่อมต่อ เขียนข้อมูลบางส่วนไปยังไคลเอนต์ (หากต้องเขียน) ปิดการเชื่อมต่อและรอการเชื่อมต่อครั้งถัดไป
ปรับปรุงโค้ดก่อนหน้าและสร้างโค้ดต่อไปนี้เพื่อสร้างเซิร์ฟเวอร์ใหม่ของคุณ:
<?php
// ตั้งค่าซ็อกเก็ตของเรา
$commonProtocol = getprotobyname("tcp");
$socket = socket_create(AF_INET, SOCK_STREAM, $commonProtocol);
socket_bind($socket, 'localhost', 1337); //socket_bind() ผูกซ็อกเก็ตเข้ากับที่อยู่ IP และพอร์ต
socket_listen($ซ็อกเก็ต);
//เตรียมใช้งานบัฟเฟอร์
$buffer = "ไม่มีข้อมูล";
ในขณะที่ (จริง) {
// ยอมรับการเชื่อมต่อใด ๆ ที่เข้ามาในซ็อกเก็ตนี้
$connection = socket_accept($socket);//socket_accept() ยอมรับการเชื่อมต่อแบบ Socket
printf("เชื่อมต่อซ็อกเก็ตrn");
// ตรวจสอบว่ามีอะไรอยู่ในบัฟเฟอร์หรือไม่
ถ้า($buffer != ""){
printf("มีบางอย่างอยู่ในบัฟเฟอร์...กำลังส่งข้อมูล...rn");
socket_write($connection, $buffer . "rn"); //socket_write() เขียนข้อมูลลงในซ็อกเก็ตแคช
printf("เขียนถึง socketrn");
}อื่น {
printf("ไม่มีข้อมูลในบัฟเฟอร์rn");
-
//รับอินพุต
while($data = socket_read($connection, 1024, PHP_NORMAL_READ))//socket_read() อ่านข้อมูลที่มีความยาวตามที่กำหนด
-
$บัฟเฟอร์ = $ข้อมูล;
socket_write($connection, "ข้อมูลที่ได้รับrn");
printf("บัฟเฟอร์: " . $buffer . "rn");
-
socket_close($connection); //socket_close() ปิดทรัพยากรซ็อกเก็ต
printf("ปิดซ็อกเก็ตrnrn");
-
-
เซิร์ฟเวอร์นี้ควรทำอย่างไร? เริ่มต้นซ็อกเก็ตและเปิดแคชเพื่อส่งและรับข้อมูล รอการเชื่อมต่อและเมื่อทำการเชื่อมต่อแล้ว ระบบจะพิมพ์ "Socket เชื่อมต่อ" บนหน้าจอฝั่งเซิร์ฟเวอร์ เซิร์ฟเวอร์นี้จะตรวจสอบบัฟเฟอร์และหากมีข้อมูลอยู่ในบัฟเฟอร์ เซิร์ฟเวอร์จะส่งข้อมูลไปยังคอมพิวเตอร์ที่เชื่อมต่อ จากนั้นจะส่งข้อความยอมรับข้อมูลนี้ เมื่อยอมรับข้อความแล้ว ระบบจะบันทึกข้อความลงในข้อมูล ทำให้คอมพิวเตอร์ที่เชื่อมต่อทราบถึงข้อความ และปิดการเชื่อมต่อในที่สุด เมื่อการเชื่อมต่อถูกปิด เซิร์ฟเวอร์จะเริ่มประมวลผลการเชื่อมต่อครั้งถัดไป
◆ มันง่ายที่จะสร้างไคลเอนต์เพื่อจัดการกับปัญหาที่สอง คุณต้องสร้างหน้า PHP เชื่อมต่อกับซ็อกเก็ต ส่งข้อมูลบางส่วนไปยังแคชและประมวลผล จากนั้นคุณจะมีข้อมูลที่ประมวลผลรออยู่ และคุณสามารถส่งข้อมูลของคุณไปยังเซิร์ฟเวอร์ได้ ในการเชื่อมต่อไคลเอนต์อื่น ระบบจะประมวลผลข้อมูลนั้น
ตัวอย่างต่อไปนี้แสดงให้เห็นถึงการใช้ซ็อกเก็ต:
<?php
// สร้างซ็อกเก็ตและเชื่อมต่อ
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$connection = socket_connect($socket,'localhost', 1337);
ในขณะที่($buffer = socket_read($socket, 1024, PHP_NORMAL_READ)) {
if($buffer == "ไม่มีข้อมูล") {
echo(“<p>ไม่มีข้อมูล</p>”);
หยุดพัก;
}อื่น{
// ทำบางอย่างกับข้อมูลในบัฟเฟอร์
echo(“<p>ข้อมูลบัฟเฟอร์: “ . $buffer . “</p>”);
-
-
echo(“<p>กำลังเขียนไปยังซ็อกเก็ต</p>”);
// เขียนข้อมูลทดสอบลงในซ็อกเก็ตของเรา
if(!socket_write($socket, “ข้อมูลบางส่วนrn”)){
echo(“<p>เขียนล้มเหลว</p>”);
-
// อ่านการตอบสนองใด ๆ จากซ็อกเก็ต
ในขณะที่($buffer = socket_read($socket, 1024, PHP_NORMAL_READ)){
echo(“<p>ข้อมูลที่ส่งคือ: ข้อมูลบางส่วน<br> การตอบสนองคือ:" . $buffer . “</p>”);
-
echo(“<p>อ่านเสร็จแล้วจากซ็อกเก็ต</p>”);
-
โค้ดตัวอย่างนี้สาธิตให้ลูกค้าเชื่อมต่อกับเซิร์ฟเวอร์ ลูกค้าอ่านข้อมูล หากนี่เป็นการเชื่อมต่อแรกที่มาถึงในรอบนี้ เซิร์ฟเวอร์จะส่ง "ไม่มีข้อมูล" กลับไปยังไคลเอนต์ หากสิ่งนี้เกิดขึ้น ไคลเอ็นต์จะอยู่ด้านบนของการเชื่อมต่อ ลูกค้าส่งข้อมูลไปยังเซิร์ฟเวอร์ ข้อมูลจะถูกส่งไปยังเซิร์ฟเวอร์ และลูกค้ารอการตอบกลับ เมื่อได้รับคำตอบแล้ว ระบบจะเขียนคำตอบไปที่หน้าจอ