Tidak dapat menentukan peta port ke port IP internal
Tapi saya telah memetakan IP eksternal ke Server Linux internal.
Tapi saya juga ingin menggunakan VNC untuk terhubung ke komputer Windows internal dari luar.
Jadi saya menulis program ini dan prinsipnya seperti ini
Program ini akan membuka port di Server Linux untuk tindakan mendengarkan. Ketika koneksi eksternal terhubung ke port ini, program akan membuka koneksi lain ke VNC Windows internal dan membuang paket eksternal secara utuh ke koneksi VNC online, dan kemudian membuang data yang dikembalikan oleh koneksi VNC secara utuh kembali ke port eksternal.
Kode program:
#!/usr/bin/php -q
<?php
$IP = '192.168.1.1' ; //IP komputer Windows
$Port = '5900' ; //Port yang digunakan oleh VNC
$ServerPort = '9999' ; //Port yang digunakan oleh Server Linux secara eksternal
$RemoteSocket = false ; //Hubungkan ke Soket VNC
fungsi SinyalFungsi & #40;$Sinyal)
& #123;
//Ini adalah fungsi pemrosesan pesan dari Proses utama
global $PID ; //PID Proses Anak
alihkan & #40;$Sinyal)
& #123;
kasus SIGTRAP & #58;
kasus SIGTERM & #58;
//Terima Sinyal untuk mengakhiri program
jika& #40;$PID)
& #123;
//Kirim sinyal SIGTERM ke Child untuk memberitahunya agar segera mengakhirinya.
posix_kill & #40;$PID,SIGTERM);
//Tunggu hingga Proses Anak selesai untuk menghindari zombie
pcntl_tunggu & #40;$Status);
& #125;
//Tutup Socket yang dibuka oleh Proses utama
HancurkanSocket & #40;);
exit& #40;0); //Akhiri Proses utama
merusak;
kasus SIGCHLD & #58;
/*
Ketika Proses Anak berakhir, Anak akan mengirimkan sinyal SIGCHLD ke Induk
Ketika Induk menerima SIGCHLD, ia mengetahui bahwa Proses Anak telah berakhir dan harus mengambil beberapa tindakan pengakhiran*/
unset& #40;$PID); //Hapus $PID untuk menunjukkan bahwa Proses Anak telah berakhir
pcntl_tunggu & #40;$Status); //Hindari Zombi
merusak;
bawaan& #58;
& #125;
& #125;
fungsi ChildSignalFunction & #40;$Signal)
& #123;
//Ini adalah fungsi pemrosesan pesan dari Proses Anak
alihkan & #40;$Sinyal)
& #123;
kasus SIGTRAP & #58;
kasus SIGTERM & #58;
//Proses Anak menerima pesan akhir
DestroySocket & #40;); //Tutup Soket
exit& #40;0); //Akhiri Proses Anak
bawaan& #58;
& #125;
& #125;
fungsi ProcessSocket & #40;$ConnectedServerSocket)
& #123;
//Fungsi pemrosesan Soket Proses Anak
//$ConnectedServerSocket -> Socket yang terhubung secara eksternal
global $ServerSocket , $RemoteSocket , $IP , $Port ;
$ServerSocket = $ConnectedServerSocket ;
menyatakan& #40;ticks = 1); //Baris ini harus ditambahkan, jika tidak, fungsi pemrosesan pesan tidak dapat diatur.
//Mengatur fungsi pemrosesan pesan
jika& #40;!pcntl_signal(SIGTERM, "Fungsi ChildSignal"))
jika& #40;!pcntl_signal(SIGTRAP, "Fungsi ChildSignal"))
//Buat Socket yang terhubung ke VNC
$RemoteSocket = soket_buat & #40;AF_INET, SOCK_STREAM,SOL_TCP);
//Hubungkan ke VNC internal
@ $RemoteConnected = soket_koneksi & #40;$RemoteSocket,$IP,$Port);
if& #40;!$RemoteConnected) kembali; //Tidak dapat terhubung ke ujung VNC
//Atur pemrosesan Socket ke Nonblock untuk mencegah pemblokiran program
jika& #40;!socket_set_nonblock($RemoteSocket))
jika& #40;!socket_set_nonblock($ServerSocket))
sementara & #40;benar)
& #123;
//Di sini kita menggunakan pooling untuk mendapatkan data
$NoRecvData = false ; //Variabel ini digunakan untuk menentukan apakah koneksi eksternal telah membaca data.
$NoRemoteRecvData = false ; //Variabel ini digunakan untuk menentukan apakah koneksi VNC telah membaca data.
@ $RecvData = soket_read & #40;$ServerSocket,4096,PHP_BINARY_READ);
//Baca 4096 byte data dari koneksi eksternal
@ $RemoteRecvData = soket_read & #40;$RemoteSocket,4096,PHP_BINARY_READ);
//Baca 4096 byte data dari koneksi vnc
jika& #40;$RemoteRecvData==='')
& #123;
//Koneksi VNC terputus, saatnya diakhiri
echo "Tutup Koneksi Jarak Jauhn" ;
kembali;
& #125;
jika& #40;$RemoteRecvData===salah)
& #123;
/*
Karena kita menggunakan mode nonblobk, situasinya di sini adalah koneksi vnc tidak memiliki data untuk dibaca.
*/
$NoRemoteRecvData = benar ;
//Hapus Kesalahan Terakhir
socket_clear_error & #40;$RemoteSocket);
& #125;
jika& #40;$RecvData==='')
& #123;
//Koneksi eksternal terputus, saatnya diakhiri
echo "Koneksi Klien Tutupn" ;
kembali;
& #125;
jika& #40;$RecvData===salah)
& #123;
/*
Karena kami menggunakan mode nonblobk, situasinya di sini adalah tidak ada data yang tersedia untuk dibaca dari koneksi eksternal.
*/
$NoRecvData = benar ;
//Hapus Kesalahan Terakhir
socket_clear_error & #40;$ServerSocket);
& #125;
jika& #40;$NoRecvData&&$NoRemoteRecvData)
& #123;
//Jika koneksi eksternal maupun koneksi VNC tidak memiliki data untuk dibaca,
//Biarkan program tidur selama 0,1 detik untuk menghindari penggunaan sumber daya CPU dalam jangka panjang
gunakan tidur & #40;100000);
//Setelah bangun, lanjutkan tindakan pengumpulan untuk membaca soket
melanjutkan;
& #125;
//Data Penerimaan
jika& #40;!$NoRecvData)
& #123;
//Koneksi eksternal membaca data
sementara & #40;benar)
& #123;
//Mentransfer data yang dibaca dari koneksi eksternal ke koneksi VNC
@ $WriteLen = soket_tulis & #40;$RemoteSocket,$RecvData);
jika& #40;$WriteLen===salah)
& #123;
//Karena masalah transmisi jaringan, data tidak dapat ditulis saat ini.
//Tidur selama 0,1 detik sebelum mencoba lagi.
gunakan tidur & #40;100000);
melanjutkan;
& #125;
jika& #40;$WriteLen===0)
& #123;
//Koneksi jarak jauh terputus, program harus berakhir
echo "Tutup Sambungan Tulis Jarak Jauhn" ;
kembali;
& #125;
//Ketika data yang dibaca dari koneksi eksternal telah sepenuhnya dikirim ke koneksi VNC, loop ini terputus.
jika& #40;$WriteLen==strlen($RecvData)) rusak;
//Jika data tidak dapat dikirim dalam satu waktu, maka harus dipecah menjadi beberapa transmisi hingga semua data terkirim.
$RecvData = substr & #40;$RecvData,$WriteLen);
& #125;
& #125;
jika& #40;!$NoRemoteRecvData)
& #123;
//Berikut adalah data yang dibaca dari koneksi VNC dan kemudian ditransfer kembali ke koneksi eksternal.
//Prinsipnya hampir sama seperti diatas dan saya tidak akan panjang lebar lagi.
sementara & #40;benar)
& #123;
@ $WriteLen = socket_write & #40;$ServerSocket,$RemoteRecvData);
jika& #40;$WriteLen===salah)
& #123;
gunakan tidur & #40;100000);
melanjutkan;
& #125;
jika& #40;$WriteLen===0)
& #123;
echo "Tutup Sambungan Tulis Jarak Jauhn" ;
kembali;
& #125;
jika& #40;$WriteLen==strlen($RemoteRecvData))
$RemoteRecvData = substr & #40;$RemoteRecvData,$WriteLen);
& #125;
& #125;
& #125;
& #125;
fungsi DestroySocket & #40;)
& #123;
//Digunakan untuk menutup Socket yang terbuka
global $ServerSocket , $RemoteSocket ;
jika& #40;$RemoteSocket)
& #123;
//Jika koneksi VNC sudah diaktifkan
//Socket harus dimatikan sebelum menutup Socket, jika tidak pihak lain tidak akan mengetahui bahwa Anda telah menutup koneksi.
@ socket_shutdown & #40;$RemoteSocket,2);
socket_clear_error & #40;$RemoteSocket);
//Tutup Soket
socket_close & #40;$RemoteSocket);
& #125;
//Tutup koneksi eksternal
@ socket_shutdown & #40;$ServerSocket,2);
socket_clear_error & #40;$ServerSocket);
socket_close & #40;$ServerSocket);
& #125;
//Ini adalah awal dari keseluruhan program, dan program mulai dieksekusi dari sini
//Pertama jalankan fork di sini
$PID = pcntl_fork & #40;);
if& #40;$PID==-1) mati("tidak bisa bercabang");
//Jika $PID bukan 0, berarti ini adalah Proses Induk
//$PID adalah Proses Anak
//Ini adalah Proses Induk. Akhiri sendiri dan biarkan Anak menjadi Daemon.
jika& #40;$PID) mati("Daemon PID:$PIDn");
//Mulai dari sini, mode Daemon dijalankan.
//Lepaskan Proses saat ini dari terminal dan masuk ke mode daemon
if& #40;!posix_setsid()) mati("tidak dapat melepaskan diri dari terminaln");
//Mengatur fungsi pemrosesan pesan daemon
menyatakan& #40;centang = 1);
jika& #40;!pcntl_signal(SIGTERM, "SignalFunction")) mati("Error!!!n");
jika& #40;!pcntl_signal(SIGTRAP, "SignalFunction")) mati("Error!!!n");
jika& #40;!pcntl_signal(SIGCHLD, "Fungsi Sinyal")) mati("Kesalahan!!!n");
//Membuat Socket untuk koneksi eksternal
$ServerSocket = soket_buat & #40;AF_INET, SOCK_STREAM,SOL_TCP);
//Atur IP dan Port untuk pemantauan koneksi eksternal. Atur bidang IP ke 0, yang berarti mendengarkan IP semua antarmuka.
if& #40;!socket_bind($ServerSocket,0,$ServerPort)) mati("Tidak Dapat Mengikat Soket!n");
//Mulai mendengarkan Port
jika& #40;!socket_listen($ServerSocket)) mati("Tidak Dapat Mendengarkan!n");
//Atur Socket ke mode non-blok
if& #40;!socket_set_nonblock($ServerSocket)) mati("Tidak Dapat Mengatur Soket Server ke Blokir!n");
//Hapus variabel $PID, yang menunjukkan bahwa saat ini tidak ada Proses Anak
tidak disetel& #40;$PID);
sementara & #40;benar)
& #123;
//Masuk ke mode pooling dan periksa apakah ada koneksi setiap 1 detik.
tidur & #40;1);
//Periksa apakah ada koneksi masuk
@ $ConnectedServerSocket = soket_accept & #40;$ServerSocket);
jika& #40;$ConnectedServerSocket!==salah)
& #123;
//Seseorang masuk
//Mulai Proses Anak untuk menangani koneksi
$PID = pcntl_fork & #40;);
if& #40;$PID==-1) mati("tidak bisa bercabang");
if& #40;$PID) lanjutkan;//Ini adalah proses daemon, terus pantau.
//Inilah awal dari Proses Anak
//Jalankan fungsi di Socket
ProcessSocket & #40;$ConnectedServerSocket);
//Setelah memproses Socket, akhiri Socket
HancurkanSocket & #40;);
//Akhiri Proses Anak
keluar& #40;0);
& #125;
& #125;
?>