Bikin websocket dengan PHP, dan cara kerja websocket
Tidak seperti bahasa pemrograman lainnya, implementasi websocket dalam bahasa pemrograman PHP jauh lebih rumit. Bahkan jika kita berlangganan pada layanan webhosting, kebanyakan dari mereka tidak mendukung protokol socket server.
Kenapa sih begitu rumit membuat websocket dalam PHP? Mungkin kalian bertanya demikian, saya juga pernah seperti kalian. Butuh waktu yang cukup lama untuk mepelajari websocket dalam PHP, tidak hanya sebatas mengimplementasikanya saja.
Kita harus mengetahui bagaimana mekanisme kerja dari sebuah websocket. Dan inilah hasil dari pengalaman yang pernah saya lalui. Websocket sebenranya menggunakan protokol yang berbeda dengan HTTPS. Ini cukup berebeda dengan web standar, oleh sebab itu tidak sembarangan dalam menyiapakan websocket server.
Selain itu juga aplikasi websocket harus berjalan secara mandiri dari sistem kita, inilah yang menyebabkan tidak semua web hosting mendukung websocket. PHP secara universal konfigurasi mereka sudah di atur oleh webserver, beda sama bahasa pemrograman lain.
Dimana environment program dan library apapun yang di butuhkan di sertakan dalam folder program. Contoh sepert bahasa JavaScript dengan engine nodejs, python, golang dan sebagainya. Kalau PHP web serverlah yang menyediaakan konfigurasi environment, sehingga apapun yang kita butuhkan plugin atau fiturnya harus di aktifkan lewat konfigurasi web server.
Nah program websocket itu merupakan program yang berjalan sendiri di latar belakang. Kita menjalankan skrip PHP ke dalam daemon, dan skrip ini bertindak untuk mendengarkan masukan data dari protokol nya sendiri yang di bedakan dengan server utama. Biasanya server utama untuk mengakses web menggunakan pengalokasian port 80 secara default.
Untuk webscoket kita harus membuat port yang berbeda, ini wajib karena websocket tidak bisa berjalan pada koneksi https pada umumnya. Jika kalian pernah berhasil membuat websocket di localhost, itu karena konfigurasi telah di atur dengan baik, serta kalian punya kontrol terhadap firewall untuk membuka port tertentu.
Lalu bagaimana caranya untuk membuat websocket server? Sebelum masuk ke pembahasan, pastikan anda mempunyai akses ke sistem server yang akan di gunakan. Karena ini akan membutuhkan hak akses administrator khusus, dimana kita harus menjalankan skrip processor websocket ke dalam task/deaemon ( background process ).
Anggaplah saja nama file nya adalah server.php, nah file ini harus di jalankan dalam background process sebagai aplikasi terpisah. Ia tidak dapat di panggil menggunakan https://domain.com/server.php, ia harus di daftarkan sebagai background process.
Beberapa orang mungkin menggunakan mekanisme cron job agar file tersebut tetap dapat berjalan. Namun metode tersebut tidak cocok. Karena webscoket membutuhkan koneksi yang stabil serta tidak terhenti ditengah jalan. Jika menggunakan cron job, skrip server.php kita akan berhenti berjalan dan berhenti mendengarkan pesan dari port tertentu yang pernah di buat. Dan ini menyebabkan koneksi webscoket terputus.
Setting Konfigurasi websocket
Untuk mengkonfigurasi websocket kita membutuhkan sebuah modul proxy khususnya untuk web server apache. Silakan edit file httpd.conf, cari teks "LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so", hapus tanda # untuk mengaktifkan modul ini. Lokasi file conf ada di folder /www/server/apache/conf jika menggunakan aaPanel. Tapi sama, file ini terletak di folder apache dan folder conf.Untuk web server nginx tidak perlu. Sekarang kita lanjut mengarahkan sebuah proxy ke aplikasi internal yang akan berjalan di latar belakang sistem kita. Ibaratkanya kita melakukan routing URL. Silakan masuk ke folder konfigurasi website anda untuk mengedit virtualhost.
Tambahkan baris ini di dalam kode setelan <VirtualHost *:80>
ProxyPass /websocket ws://IP-LOCAL:PORT
ProxyPassReverse /websocket ws://IP-LOCAL:PORT
Khusus nginx silakan edit modrewrite pada situs anda untuk menambahkan routing websocket :
location /websocket {
proxy_pass http://IP-LOCAL:PORT;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
Di atas kita membuat sebuah proxy untuk melakukan routing. Jadi permintaan yang masuk dapat di forwading ke aplikasi yang berjalan dalam hal ini adalah server.php. Kamu bisa menggunakan ws://IP-SERVER--NETWORK:PORT/websocket. Penjelasan lebih detail silakan cek di bawah ini :
- Penggunaan Proxy wajib, karena kita memforwading permintaan ke aplikasi lain dalam server local. Fungsinya adalah menerima permintaan dari jaringan dan meneruskanya ke dalam app local.
- Setiap aplikasi lokal punya port tersediri, port mengarahkanya untuk berkomunikasi. Satu aplikasi berjalan satu port tidak bolah konflik jadi kamu harus membuat port yang unik dan tidak digunakan oleh aplikasi lain.
- Jika anda menggunakan firewall, tambahkan port yang di gunakan pada firewall ini agar port tersebut dapat di akses lewat jaringan internet alis public network. Tanpa itu, ip hanya dapat di akses lewat lokal saja.
- Koneksi menggunakan ws://, karena kita mencoba menggunakan koneksi yang tidak ter-enkripsi oleh SSL. Ingat, beda antara HTTP dan WS, komunikasi kita berada pada network berbeda.
Tahap terakhir adalah mengaktifkan fungsi exec(). Kenapa? Karena kita akan menjalankan PHP server.php sebagai background process menggunakan fungsi tersebut. Untuk mengaktifknaya masuk ke manajemen PHP version yang anda gunakan, kemudian pilih disabled function hapus nama exec untuk mengaktifkanya. Tergantung pada jenis panel yang anda gunakan, di sini saya menggunakan aaPanel.
Jangan lupa pada firewall untuk di tambahkan port yang akan di gunakan. Firewall itu ibaratkan seperti whitelist, dimana ip yang di tambahkan dan di konfigurasi akan di izinkan untuk dapat menerima data langsung lewat jaringan yang terhubung. Jika tidak, maka port hanya akan dapat di akses secara lokal saja. Di sini saya menambahkan port sembarang 8183
Setelah selesai, setup silakan download skrip yang saya berikan berikut ini Pass : ryanid . Cara pakainya, gampang, silakan panggil http://domain-kamu.com/run.php, skrip akan menjalankan server.php sebagai backrgound process PID nya akan di simpan ke dalam file. Ini berguna untuk melakukan kill process.
Pada saat skrip berjalan, pada manajemen firewall anda akan melihat teks listen pada port yang di gunakan. Skrip di atas menggunakna port 8183, listen artinya ada program di server kita yang mendengarkan port tersebut. Sehingga apabila ada data yang masuk lewat port tersebut akan di tangkap oleh aplikasi server.php
Panggil http://domain-kamu.com/ untuk menjalankan index chat sederhana. Saya mendesain server.php untuk menerima response dan memasukanya ke dalam file json. Hanya sebatas contoh, silakan kreasikan sendiri sesuka hati.
Skrip yang saya bagikan ini adalah basic, menggunakan library PHP ratchet dan fancywebsocket.js. Mungkin kalian bertanya, kenapa tidak menggunakan URL ws://IP-SERVER:8183/server.php. Sebenarnya itu adalah metode yang salah, websocket tidak bisa berjalan pada HTTP biasa, dan itu akan bentrok dengan koneksi yang digunakan oleh halaman web.
Websocket itu menggunakan jalur komunikasi sendiri yang tidak saling terkait dengan HTTP utama. Ini memungkinkan komunikasi 2 arah, antara server dan client. Koneksi websocket tetap terhubung ke server terus menerus. Ini mengurangi latency, karena tidak perlu memulai koneksi baru untuk mengirimkan dan menerima data.
Itulah sebabnya kita butuh proxy untuk melakukan routing. Tujuanya mengarahkan semua permintaan masuk ke aplikasi yang berjalan yang dapat menerima data socket. Dalam hal ini adalah server.php yang sudah kita persiapkan untuk mendengarkan port 8183.
Perlu di ketahui, websocket di atas tidak menggunakan SSL. Jika anda menggunakan ssl dalam domain, sebaiknya matikan terlebih dahulu. Atau silakan cari cara mengkonfigurasi SSL agar server dapat terhubung ke websocket. Penggunaan SSL juga mempersulit dalam penyiapan websocket, itulah sebabnya saya lebih refers ke penggunaan Server Sent Events.
Cara menggunakan SSL pada websocket di Apache dengan SSL Cloudflare
Untuk menggunakan websocket di level produksi kita harus menggunakan SSL dan juga reverse proxy. Metode reverse proxy adalah untuk mencegah IP kita terexpost ke publik, dan juga mengamankan lalu lintas koneksi internet.Untuk dapat mencapai ini, kita harus terlebih dahulu memasang sertifikat SSL di server dan juga di domain. Karena SSL itu berbayar, kita gunakan saja sertifikat yang di sediakan oleh Cloudflare mumpung masih gratis. Cara membuatnya silahkan ikuti panduan berikut ini.
- Masuk ke cloudflare dan pilih salah satu domain yang ingin anda gunakan sebagai websocket.
- Navigasi ke menu Network, Centang Opsi Websocket di sana untuk menerima permintaan dari socket.
- Kemudian Navigasi ke menu SSL/TLS, Pilih Origin Server.
- Klik create certificate, biarkan config default jangan ubah langsung generate saja.
- Setelah selesai silakan tambahkan sertifikat tersebut ke web server anda.
- Setelah menambahkan masuk ke menu SSL/TLS overview. Pada bagian Your SSL/TLS encryption mode Pilih Full/Strict
Saya penggunaa aaPanel dan web server Apache untuk menambahkan SSL di server bisa masuk ke aaPanel, navigasi ke menu website. Kemudian pilih Conf pada salah satu website yang ingin di pasangi, akan muncul menu configuration. Laku cari SSL, pada menu ssl di bagian other certificate silakan tambahkan sertifikat yang di generate tadi.
Catatan: jika anda punya banyak website di bawah domain utama, artinya setiap subdomain tersebut harus di upgarde SSL nya menggunakan SSL dari cloudflare. JIka tidak maka permintaan ke subdomain akan di forwading atau di reverse ke domain utama semua. Ini adalah bagian dari keamanan.
Setelah selesai melakukanya, sekarang buat configuration VirtualHost, pada aaPanel ini terletak di menu Website » Conf » Config, di sana akan terlihat sebuah virtualhost berjudul <VirtualHost *:443>, virtualhost ini di gunakan untuk menerima permintaan yang berasal dari SSL/TLS atau dikenal HTTPS. Silakan tambahakn configurasi virtual Proxy seperti ini.
# Off artinya cegah jadi proxy ke internet
# On artinya pertahankan header
ProxyRequests off
ProxyPreserveHost On
ProxyPass /websocket ws://IP-SERVER:PORT
ProxyPassReverse /websocket ws://IP-SERVER:PORT
Jika anda menggunakan IP server publik, wajib sekali membuka firewall dari PORT yang di gunakan. Kecuali anda hanya menggunakan IP server lokal yang dimana tidak ada akses koneksi dari jaringan internet tidak perlu membuka firewall pada port yang di gunakan.
ProxyRequests kita off kan untuk mencegah permintaan proxy, ini bagian dari keamanan agar tidak ada orang lain memanfaatkan web kita sebagai proxy mereka dalam mengakses internet. Kemudian ProxyPreserveHost kita on kan untuk mempertahankan header Host pada permintaan yang diteruskan melalui proxy. Ini berguna ketika server melakukan reverse proxy ke server lain dan Anda ingin header Host tetap tidak berubah saat meneruskan permintaan.
Silakan uji Server websocket anda dengan mengunjungi https://yourdomain.com/websocket. Jika muncul error seperti di bawah ini artinya anda terhubung ke server websocket dengan koneksi yang akan di upgrade namun browser tidak dapat menampilkan permintaan di bawah https.
Bila masih bermasalah dalam melakukan setup webscoket khusus Apache server dan Cloudflare silakan contact saya. Saya bisa bantu untuk mengkonfigurasikan websocket anda dengan fee Rp 50 ribu aja.