الیکٹران آئی پی سی (IPC) مواصلت کی حقیقی مثالوں کے ساتھ وضاحت

الیکٹران انٹر پروسیس کمیونیکیشن ڈایاگرام

الیکٹران (Electron) ویب ٹیکنالوجیز جیسے HTML، CSS اور JavaScript کا استعمال کرتے ہوئے کراس پلیٹ فارم ڈیسک ٹاپ ایپلی کیشنز بنانے کے لیے سب سے مقبول فریم ورکس میں سے ایک ہے۔ پردے کے پیچھے، الیکٹران ایک کثیر پروسیس (multi-process) آرکیٹیکچر چلاتا ہے جس میں ایک مین پروسیس (Main Process) (جو Node.js چلاتا ہے) اور ایک یا زیادہ رینڈرر پروسیسز (Renderer Processes) (جو UI پیش کرنے کے لیے Chromium چلاتے ہیں) شامل ہوتے ہیں۔

سیکیورٹی خطرات کی وجہ سے، جدید الیکٹران ایپلی کیشنز رینڈرر پروسیس کو آپریٹنگ سسٹم سے الگ (isolate) رکھتی ہیں۔ اس کا مطلب ہے کہ آپ رینڈرر UI سے براہ راست Node.js ماڈیولز یا سسٹم کے وسائل (جیسے فائلیں پڑھنا یا ڈیٹا بیس میں سوالات کرنا) تک رسائی حاصل نہیں کر سکتے۔

اس فرق کو محفوظ طریقے سے ختم کرنے کے لیے، الیکٹران انٹر پروسیس کمیونیکیشن (IPC) کا استعمال کرتا ہے۔

اس گائیڈ میں، ہم وضاحت کریں گے کہ الیکٹران IPC کیسے کام کرتا ہے اور حقیقی، پروڈکشن کے لیے تیار کوڈ کی مثالوں کے ساتھ تین بنیادی مواصلاتی پیٹرن تلاش کریں گے۔


1. رینڈرر سے مین پروسیس (ایک طرفہ / One-Way)

یہ پیٹرن اس وقت استعمال ہوتا ہے جب رینڈرر کسی ردعمل کا انتظار کیے بغیر مین پروسیس کو کوئی کمانڈ یا ایکشن بھیجنا چاہتا ہے۔ ایک عام مثال ایپلی کیشن ونڈو کو چھوٹا یا بند کرنے کے لیے UI میں بٹن پر کلک کرنا ہے۔

آئیے دیکھتے ہیں کہ اسے تین اہم فائلوں: main.js ، preload.js ، اور renderer.js میں کیسے لاگو کیا جاتا ہے۔

مین پروسیس (main.js)

ہم رینڈرر پروسیس سے آنے والے ایونٹس کو سننے کے لیے ipcMain.on کا استعمال کرتے ہیں۔

const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');

function createWindow() {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      contextIsolation: true,
      nodeIntegration: false
    }
  });
  win.loadFile('index.html');
}

// رینڈرر سے 'close-app' ایونٹ سنیں
ipcMain.on('close-app', () => {
  app.quit();
});

پری لوڈ سکرپٹ (preload.js)

ہم رینڈرر کو پورا ipcRenderer ماڈیول فراہم کیے بغیر ایک محفوظ ریپر فراہم کرنے کے لیے contextBridge.exposeInMainWorld کا استعمال کرتے ہیں۔

const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('electronAPI', {
  closeApp: () => ipcRenderer.send('close-app')
});

رینڈرر پروسیس (renderer.js)

ہم window آبجیکٹ پر فراہم کردہ فنکشن کو کال کرتے ہیں۔

const closeButton = document.getElementById('close-btn');

closeButton.addEventListener('click', () => {
  window.electronAPI.closeApp();
});

2. رینڈرر سے مین پروسیس (دو طرفہ / درخواست-جواب)

یہ پیٹرن اس وقت استعمال ہوتا ہے جب رینڈرر کو مین پروسیس سے ڈیٹا کی درخواست کرنے یا سسٹم آپریشن شروع کرنے اور نتیجے کا انتظار کرنے کی ضرورت ہوتی ہے (جیسے، فائل پڑھنا یا ڈیٹا بیس میں محفوظ سوال کرنا)۔

ہم مین پروسیس میں ipcMain.handle اور پری لوڈ سکرپٹ میں ipcRenderer.invoke کا استعمال کرتے ہیں۔

مین پروسیس (main.js)

ipcMain.handle کا استعمال کرتے ہوئے درخواست سنیں اور غیر مطابقت پذیر (asynchronously) طور پر ڈیٹا واپس کریں۔

const { ipcMain } = require('electron');
const fs = require('fs/promises');

// 'read-file' کال کو غیر مطابقت پذیر طریقے سے سنبھالیں
ipcMain.handle('read-file', async (event, filePath) => {
  try {
    const data = await fs.readFile(filePath, 'utf-8');
    return { success: true, content: data };
  } catch (error) {
    return { success: false, error: error.message };
  }
});

پری لوڈ سکرپٹ (preload.js)

ایک غیر مطابقت پذیر ریپر فراہم کریں جو ایک Promise واپس کرتا ہے۔

const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('electronAPI', {
  readFile: (filePath) => ipcRenderer.invoke('read-file', filePath)
});

رینڈرر پروسیس (renderer.js)

واپس آنے والے Promise کے حل ہونے کا انتظار کرنے کے لیے await کا استعمال کریں۔

const readBtn = document.getElementById('read-btn');

readBtn.addEventListener('click', async () => {
  const result = await window.electronAPI.readFile('/path/to/file.txt');
  if (result.success) {
    console.log('فائل کا مواد:', result.content);
  } else {
    console.error('فائل پڑھنے میں ناکامی:', result.error);
  }
});

3. مین پروسیس سے رینڈرر (ایک طرفہ اطلاع)

یہ پیٹرن اس وقت استعمال ہوتا ہے جب مین پروسیس کو رینڈرر پروسیس میں اپ ڈیٹس یا اطلاعات بھیجنے کی ضرورت ہوتی ہے (جیسے، ڈاؤن لوڈ کی رفتار کا بار اپ ڈیٹ، ایپلی کیشن مینو کلکس، یا پس منظر کی سروس اسٹیٹس اپ ڈیٹ)۔

ہم مین پروسیس میں webContents.send اور پری لوڈ سکرپٹ میں ipcRenderer.on کا استعمال کرتے ہیں۔

مین پروسیس (main.js)

فعال ونڈو کے webContents حاصل کریں اور پیغام بھیجیں۔

// مثال: ڈاؤن لوڈ کی ترقی کے اپ ڈیٹس بھیجنا
function trackDownloadProgress(mainWindow) {
  let progress = 0;
  const interval = setInterval(() => {
    progress += 10;
    mainWindow.webContents.send('download-progress', progress);
    
    if (progress >= 100) {
      clearInterval(interval);
    }
  }, 1000);
}

پری لوڈ سکرپٹ (preload.js)

ایک سبسکرپشن کا طریقہ فراہم کریں جو ایک کال بیک فنکشن لیتا ہے۔ میموری لیک کو روکنے کے لیے کلین اپ (لیسنر ہٹانے والا) فنکشن واپس کرنا ایک اچھا عمل ہے۔

const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('electronAPI', {
  onDownloadProgress: (callback) => {
    const subscription = (event, value) => callback(value);
    ipcRenderer.on('download-progress', subscription);
    
    // میموری لیک کو روکنے کے لیے کلین اپ فنکشن واپس کریں
    return () => {
      ipcRenderer.removeListener('download-progress', subscription);
    };
  }
});

رینڈرر پروسیس (renderer.js)

ایونٹس کو سبسکرائب کریں اور UI اپ ڈیٹ کریں۔

const progressBar = document.getElementById('progress-bar');

const unsubscribe = window.electronAPI.onDownloadProgress((progress) => {
  progressBar.style.width = `${progress}%`;
  progressBar.textContent = `${progress}%`;
  
  if (progress === 100) {
    console.log('ڈاؤن لوڈ مکمل ہو گیا!');
    unsubscribe(); // میموری لیک سے بچنے کے لیے لیسنر کو صاف کریں
  }
});

4. سیکیورٹی کے بہترین طریقے

الیکٹران IPC کے ساتھ کام کرتے وقت سیکیورٹی آپ کی اولین ترجیح ہونی چاہیے۔ اگر IPC محفوظ نہیں ہے تو رینڈرر پروسیس میں داخل کیا گیا بدنیتی پر مبنی کوڈ پورے آپریٹنگ سسٹم کو خطرے میں ڈال سکتا ہے۔

ان اہم قوانین پر عمل کریں:

  1. ipcRenderer کو کبھی بھی براہ راست فراہم نہ کریں: contextBridge.exposeInMainWorld('electron', ipcRenderer) نہ لکھیں۔ ایسا کرنے سے رینڈرر کو کوئی بھی IPC پیغام بھیجنے کی مکمل اجازت مل جاتی ہے، جس سے سیکیورٹی کی حدود ٹوٹ جاتی ہیں۔
  2. کانٹیکسٹ آئسولیشن (Context Isolation) فعال رکھیں: ہمیشہ webPreferences میں contextIsolation: true اور nodeIntegration: false سیٹ کریں۔
  3. ان پٹس کی توثیق کریں: مین پروسیس میں موصول ہونے والے دلائل (جیسے فائل پاتھ یا ڈیٹا بیس کے سوالات) کو چلانے سے پہلے ہمیشہ ان کی توثیق کریں۔
  4. ipcMain.on + webContents.send کے بجائے ipcMain.handle کو ترجیح دیں: درخواست-جواب پیٹرن کے لیے، invoke/handle زیادہ صاف ہے، Promise کو قدرتی طور پر حل کرتا ہے، اور متعدد لیسنر کال بیکس کے الجھاؤ سے بچاتا ہے۔

نتیجہ

آئی پی سی (IPC) مواصلت کو سمجھنا محفوظ، اعلیٰ کارکردگی والے اور مستحکم الیکٹران ایپلی کیشنز بنانے کی کلید ہے۔ کام کے لیے صحیح پیٹرن کا استعمال کر کے اور کانٹیکسٹ آئسولیشن نافذ کر کے، آپ اپنے صارفین کو محفوظ رکھتے ہوئے ڈیسک ٹاپ پر Node.js کی مکمل طاقت کا فائدہ اٹھا سکتے ہیں۔


Ghaznix بلاگ پر مزید ڈویلپر بصیرتیں تلاش کریں →