2013-05-13 13 views
7

समस्या यह है कि लंबी प्रक्रिया के लिए PHP स्क्रिप्ट निष्पादित करता रहता है कि क्लाइंट ब्राउज़र वर्तमान में कनेक्ट है या नहीं। क्या कोई संभावना है कि अगर ग्राहक ने स्क्रिप्ट को अजाक्स कॉल को समाप्त कर दिया है तो स्क्रिप्ट सर्वर पर भी समाप्त हो जाती है?PHP HTTP अनुरोध को रद्द/बंद कर दिया गया है यदि HTTP अनुरोध रद्द/बंद

1: 'प्रसंस्करण' के रूप में सर्वर पर एक मूल्य सेट

+0

कठिनाइयों के अलावा एक नया ajax कॉल सर्वर है, जो एक दूसरे PHP स्क्रिप्ट चलाना शामिल होता है के लिए बनाया जा करने के लिए होता है। उस दूसरी PHP स्क्रिप्ट को पहली PHP स्क्रिप्ट द्वारा जेनरेट किए गए थ्रेड तक पहुंच की आवश्यकता होगी। मैं ऐसा करने के कई तरीकों के बारे में सोच सकता हूं - लेकिन यह स्वचालित नहीं होगा। आपको मूल थ्रेड को किसी नए और स्वतंत्र रूप से बनाए गए थ्रेड द्वारा किसी भी तरीके से सुलभ या नियंत्रित करने के लिए अपने PHP को कोड करना सुनिश्चित करना होगा। –

+0

वास्तव में PHP का डिफ़ॉल्ट व्यवहार प्रक्रिया को निरस्त करना है यदि क्लाइंट डिस्कनेक्ट हो जाता है। – Jon

+0

@jon विंडोज सर्वर पर मेरी स्थिति में यह डिस्कनेक्शन के बाद चल रहा है। हालांकि मैं नहीं चाहता कि PHP प्रक्रिया को बंद कर दे। मुझे रोलबैक डीबी लेनदेन की आवश्यकता है और इसे सुरक्षित रूप से बंद कर दें। –

उत्तर

8

जैसा कि @ मेटाडिंग्स php द्वारा इंगित किया गया है, कनेक्शन_बॉर्टेड() नामक कनेक्शन अपरोर्ट की जांच करने के लिए एक फ़ंक्शन है। यह 1 वापस आ जाएगी, तो कनेक्शन एक लंबे सर्वर साइड प्रक्रिया में अन्यथा 0.

समाप्त होता है उपयोगकर्ता अगर ग्राहक सर्वर से सुरक्षित रूप से डिस्कनेक्ट हो गया है या वह उसके बाद ब्राउजर सर्वर बंद कर दिया है सकते हैं पता करने के लिए आवश्यकता हो सकती है प्रक्रिया बंद करो।

विशेष रूप से एक मामले में जहां आवेदन php सत्र तो का उपयोग करता है अगर हम चलाने के बाद भी ग्राहक के कट जाने तो सर्वर इस सत्र के लिए अनुत्तरदायी मिल जाएगा लंबी प्रक्रिया छोड़ दिया में

। और उसी ग्राहक से कोई अन्य अनुरोध तब तक इंतजार करेगा जब तक कि पहले की प्रक्रिया पूरी तरह से निष्पादित न हो जाए। इस स्थिति का कारण यह है कि जब प्रक्रिया चल रही है तो सत्र फ़ाइल लॉक हो जाती है। हालांकि आप इसे अनलॉक करने के लिए session_write_close() विधि को intentioanlly कॉल कर सकते हैं। लेकिन यह सभी परिदृश्यों में व्यवहार्य नहीं है, प्रक्रिया के अंत में सत्र में कुछ लिखने की आवश्यकता हो सकती है।

अब अगर हम केवल() connection_aborted कॉल एक पाश में तो यह हमेशा वापसी 0 कनेक्शन या बंद कर दिया है कि क्या है नहीं होंगे।

0 का मतलब है कि कनेक्शन निरस्त नहीं किया गया है। यह भ्रामक है।हालांकि, पुनः खोज और प्रयोगों के बाद यदि पता चला है कि आउटपुट बफर php में कारण है।

किसी लूप में डेवलपर को बंद करने के लिए सबसे पहले कुछ पाठ को प्रतिबिंबित करके क्लाइंट को कुछ आउटपुट भेजना होगा। उदाहरण के लिए:

print " "; 

के रूप में प्रक्रिया अभी भी चल रहा है, उत्पादन ग्राहक के लिए नहीं भेजा जाएगा। अब आउटपुट भेजने के लिए हमें आउटपुट बफर फ्लश करने की आवश्यकता है।

flush(); 
ob_flush(); 

और फिर यदि हम बंदरगाहों की जांच करते हैं तो यह सही परिणाम देगा।

if (connection_aborted() != 0) { 
    die(); 
} 

के बाद काम कर उदाहरण है, यह भले ही आप PHP सत्र का उपयोग कर रहे काम करेगा:

session_start(); 
ignore_user_abort (TRUE); 

file_put_contents ("con-status.txt", "Process started..\n\n"); 

for($i = 1; $i <= 15; $i ++) { 

    print " "; 

    file_put_contents ("con-status.txt", "Running process unit $i \n", FILE_APPEND); 
    sleep (1); 

    // Send output to client 
    flush(); 
    ob_flush(); 

    // Check for connection abort 
    if (connection_aborted() != 0) { 
     file_put_contents ("con-status.txt", "\nUser terminated the process", FILE_APPEND); 
     die(); 
    } 

} 

file_put_contents ("con-status.txt", "\nAll units completed.", FILE_APPEND); 

संपादित करें 07-अप्रैल-2017

कोई फास्ट उपयोग कर रहा है - विंडोज़ पर सीजीआई तो वह वास्तव में को सीजीआई थ्रेड को स्मृति से समाप्त कर सकता है जब कनेक्शन निम्न कोड का उपयोग करके निरस्त किया जाता है:

if (connection_aborted() != 0) { apache_child_terminate(); exit; }

+0

ध्यान दें कि 'flush' से पहले' ob_flush' को कॉल किया जाना चाहिए, अगर आउटपुट बफरिंग उपयोग में है (शायद ob_end_flush?) Http://stackoverflow.com/questions/4191385/php-buffer-ob-flush-vs-flush – metadings

1

एक तरह से मैं जो सबसे आसान तरीका है इस समय-समाप्ति की समस्या को संभालने के लिए है मिल गया है इस तरह के रूप में है। प्रसंस्करण करने के लिए एक स्वतंत्र धागा शुरू करें।
2: प्रारंभिक AJAX कॉल सफलता प्राप्त करता है
3: पृष्ठ पर जावास्क्रिप्ट 'प्रतीक्षा मोड' में जाता है जो हर 10 या 30 या 60 सेकंड या पांच या दस मिनट या जो भी हो (एक नया AJAX अनुरोध भेजता है स्थिति) यह पता लगाने के लिए कि सर्वर पर मान अभी भी 'प्रसंस्करण' पर सेट है या नहीं।
4: स्वतंत्र धागा पूरा करता है। यह सर्वर पर मान 'किया' करने के लिए सेट करता है।
5: पृष्ठ पर जावास्क्रिप्ट अपनी अगली प्रतीक्षा-मोड क्वेरी बनाता है, और 'पूर्ण' और उचित डेटा देता है।

4 बी: यदि बिना किसी 'किए गए' के ​​बिना एक अश्लील समय जाता है, तो यह विफलता के रूप में पंजीकृत होता है। आपकी स्थिति पर अश्लील कितना समय निर्भर करता है। 'प्रसंस्करण' से 'रद्द' करने के मान को अद्यतन करने वाला AJAX कॉल भेजें। 5 बी: स्वतंत्र थ्रेड समय-समय पर यह सुनिश्चित करने के लिए स्थिति की जांच करता है कि यह अभी भी 'प्रसंस्करण' पर सेट है। यदि यह 'रद्द' करने के लिए मोड-शिफ्ट देखता है तो यह स्वयं रद्द हो जाता है। बाहर तो चेतावनी एम्प्टर http://php.net/manual/en/function.ignore-user-abort.php

निष्पादन के बीच में एक स्क्रिप्ट रोकी अप्रत्याशित परिणाम मिल सकते हैं,

1

यह वही है जिसे आप ढूंढ रहे है। अपनी प्रसंस्करण करते समय, आप कभी-कभी प्रगति को सफलतापूर्वक रद्द करने के लिए निरस्त कनेक्शन की जांच कर सकते हैं, क्योंकि कोई इंटरेक्टिव थ्रेडिंग मॉडल में करेगा।

4

चेक पीएचपी connection_aborted() फ़ंक्शन:

+0

वाह। मुझे यह भी नहीं पता था कि यह वहां था। धन्यवाद! –

+0

@metadings यह AJAX अनुरोधों के लिए काम नहीं कर रहा है। AJAX अनुरोध समाप्त कर दिया गया है और connection_aborted() अभी भी 0 लौटाता है। यहां तक ​​कि मैंने वेब पेज को बंद करके भी कोशिश की है, स्क्रिप्ट सक्रिय होने पर भी चलती हैं। क्या कारण हो सकता है? –

+0

@metadings फ़ंक्शन कनेक्शन_बॉर्टेड() में एक बग है और यह 0 बार वापस आ जाएगा 0 इस बग को देखें: https://bugs.php.net/bug.php?id=54062 ... क्या कोई अन्य विकल्प है? –