আমি কীভাবে তাড়াতাড়ি কোনও সংযোগ বন্ধ করব?


100

আমি একটি এজ্যাক্স কল করার চেষ্টা করছি (জ্যাকুয়েরির মাধ্যমে) যা বেশ দীর্ঘ প্রক্রিয়া শুরু করবে। আমি চাই যে স্ক্রিপ্টটি কেবল একটি প্রতিক্রিয়া প্রেরণ করবে যা নির্দেশ করে যে প্রক্রিয়াটি শুরু হয়েছে, কিন্তু পিএইচপি স্ক্রিপ্টটি সঞ্চালিত না হওয়া পর্যন্ত জ্যাকুয়েরি প্রতিক্রিয়া ফিরিয়ে দেবে না।

আমি এটি "ক্লোজ" শিরোনাম (নীচে) এবং আউটপুট বাফারিং দিয়ে চেষ্টা করেছি; কোন কাজ বলে মনে হচ্ছে না। কোন অনুমান? বা JQuery এ আমার কিছু করা দরকার?

<?php

echo( "We'll email you as soon as this is done." );

header( "Connection: Close" );

// do some stuff that will take a while

mail( 'dude@thatplace.com', "okay I'm done", 'Yup, all done.' );

?>

আপনি কি নিজের আউটপুট বাফারটি ob_flush () দিয়ে ফ্লাশ করেছেন এবং এটি কার্যকর হয়নি?
ভিঙ্কো ভার্সালোভিক

উত্তর:


89

নিম্নলিখিত পিএইচপি ম্যানুয়াল পৃষ্ঠা (ব্যবহারকারী-নোটগুলি সহ) পিএইচপি স্ক্রিপ্টটি শেষ না করে কীভাবে ব্রাউজারে টিসিপি সংযোগটি বন্ধ করবেন সে সম্পর্কে একাধিক নির্দেশাবলীর পরামর্শ দেয়:

সম্ভবত এটি একটি ঘনিষ্ঠ শিরোনাম পাঠানোর চেয়ে কিছুটা বেশি প্রয়োজন।


ওপি তারপরে নিশ্চিত করে: হ্যাঁ, এটি কৌশলটি করেছে: ব্যবহারকারী-নোট # 71172 (নভেম্বর 2006) এখানে অনুলিপি করা হয়েছে:

আপনার পিএইচপি স্ক্রিপ্টটি চলমান রাখার সময় ব্যবহারকারীদের ব্রাউজার সংযোগ বন্ধ করে দেওয়া [পিএইচপি] ৪.১-এর পর থেকে যখন সমস্যাটি register_shutdown_function()পরিবর্তিত হয়েছিল যাতে এটি ব্যবহারকারীদের সংযোগটি স্বয়ংক্রিয়ভাবে বন্ধ না হয় তখন সমস্যা হয়ে দাঁড়িয়েছে।

এসটিএস এ মেইল ​​ডট এক্সবিউন ডট হু মূল সমাধান পোস্ট করেছেন:

<?php
header("Connection: close");
ob_start();
phpinfo();
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush();
flush();
sleep(13);
error_log("do something in the background");
?>

কোনটি কাজ করে জরিমানা যতক্ষণ না আপনি প্রতিস্থাপন phpinfo()জন্য echo('text I want user to see');যে ক্ষেত্রে হেডার কখনো চালাচালি হয়!

সমাধানটি হোল্ডারের তথ্য প্রেরণের আগে পরিষ্কারভাবে আউটপুট বাফারিং বন্ধ করে বাফার সাফ করা clear উদাহরণ:

<?php
ob_end_clean();
header("Connection: close");
ignore_user_abort(true); // just to be safe
ob_start();
echo('Text the user will see');
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush(); // Strange behaviour, will not work
flush(); // Unless both are called !
// Do processing here 
sleep(30);
echo('Text user will never see');
?>

এটি বের করার চেষ্টা করে মাত্র 3 ঘন্টা ব্যয় করেছেন, আশা করি এটি কাউকে সহায়তা করবে :)

পরীক্ষিত:

  • আইই 7.5730.11
  • মোজিলা ফায়ারফক্স 1.81

পরে জুলাই ২০১০-তে সম্পর্কিত উত্তরে আর্টিক ফায়ার তারপরে আরও দুটি ব্যবহারকারীর নোটকে যুক্ত করেছে যা উপরের একটিটির সাথে ফলো-আপ ছিল:



4
লেখক এবং @ টিম্বো হোয়াইট, বিষয়বস্তুর আকার না জেনে কী কী প্রাথমিকভাবে কোনও সংযোগ বন্ধ করা সম্ভব? IE, বন্ধ করার আগে কন্টেন্ট ক্যাপচার না করে।
skibulk

4
হ্যাকার এবং কৃপণ ওয়েব ব্রাউজারগুলি এখনও সংযোগ-বন্ধ এইচটিটিপি শিরোলেখটিকে উপেক্ষা করতে পারে এবং বাকি আউটপুটটি পেতে পারে .. পরবর্তী কী আসে তা সংবেদনশীল নয় তা নিশ্চিত করুন। সম্ভবত একটি ob_start (); সমস্ত কিছু দমন করার জন্য: পি
হানশেনারিক

4
ফাস্টcgi_finish_request () যুক্ত করা হচ্ছে; উপরের কাজ না করে সফলভাবে সংযোগটি বন্ধ করার কথা বলা হয়েছে। তবে, আমার ক্ষেত্রে এটি আমার স্ক্রিপ্টটি চালিয়ে যাওয়া চালিয়ে যাওয়া থেকে বাধা দিয়েছে, তাই সতর্কতার সাথে ব্যবহার করুন।
এরিক দুবé

@ রিচার্ডস্মিথ কারণ শিরোনামটি Connection: closeস্ট্যাকের অন্যান্য সফ্টওয়্যার দ্বারা ওভাররাইট করা যেতে পারে, উদাহরণস্বরূপ, সিজিআইয়ের ক্ষেত্রে বিপরীত প্রক্সিটি (আমি এনজিনেক্সের সাথে আচরণটি পর্যবেক্ষণ করেছি)। সে সম্পর্কে @hanshenrik এর উত্তর দেখুন। সাধারণভাবে, Connection: closeক্লায়েন্ট পক্ষেই মৃত্যুদন্ড কার্যকর করা হয় এবং এই প্রশ্নের উত্তর হিসাবে বিবেচনা করা উচিত নয়। সংযোগটি সার্ভার দিক থেকে বন্ধ করা উচিত ।
7heo.tk

56

এই 2 টি হেডার প্রেরণ করা প্রয়োজন:

Connection: close
Content-Length: n (n = size of output in bytes )

যেহেতু আপনার আউটপুটটির আকার জানতে হবে তাই আপনার আউটপুটটি বাফার করতে হবে, তারপরে এটি ব্রাউজারে ফ্লাশ করুন:

// buffer all upcoming output
ob_start();
echo "We'll email you as soon as this is done.";

// get the size of the output
$size = ob_get_length();

// send headers to tell the browser to close the connection
header("Content-Length: $size");
header('Connection: close');

// flush all output
ob_end_flush();
ob_flush();
flush();

// if you're using sessions, this prevents subsequent requests
// from hanging while the background process executes
if (session_id()) session_write_close();

/******** background process starts here ********/

এছাড়াও, যদি আপনার ওয়েব সার্ভার আউটপুটটিতে স্বয়ংক্রিয় gzip সংক্ষেপণ ব্যবহার করে (যেমন Mod_deflate সহ অ্যাপাচি), এটি কাজ করবে না কারণ আউটপুটটির প্রকৃত আকার পরিবর্তিত হয়েছে, এবং সামগ্রী-দৈর্ঘ্যটি আর সঠিক নয়। নির্দিষ্ট স্ক্রিপ্ট gzip সংক্ষেপণ অক্ষম করুন।

আরও তথ্যের জন্য, http://www.zulius.com/how-to/close-browser-connection-continue-xecution দেখুন


16
যদি আপনার সার্ভার আউটপুটকে সংকুচিত করে, আপনি এটিকে অক্ষম করতে পারেন সেইভাবে অ্যাপাচি এটি header("Content-Encoding: none\r\n");সংকোচিত করবে না।
GDmac

4
@ জিডিএম্যাক আপনাকে ধন্যবাদ! আমি এটি কিছুক্ষণের জন্য কাজ করতে পারি না, তবে সংক্ষেপণটি অক্ষম করে কৌশলটি করেছে।
সংশোধনী

ob_flush()প্রয়োজন নেই এবং আসলে একটি নোটিশ ঘটায় failed to flush buffer। আমি এটি বের করেছিলাম এবং এটি দুর্দান্ত কাজ করেছে।
লেবি

4
আমি দেখতে পেয়েছি যে ob_flush()লাইনটি প্রয়োজনীয় ছিল
ডিবেস্টার

21

fastcgi_end_request()ফাংশনটি ব্যবহার করতে আপনি পিএইচপি-এফপিএম সহ ফাস্ট-সিজিআই ব্যবহার করতে পারেন । ইতিমধ্যে ক্লায়েন্টের কাছে প্রতিক্রিয়া প্রেরণ করা অবস্থায় আপনি কিছু প্রক্রিয়াকরণ চালিয়ে যেতে পারেন।

আপনি এখানে পিএইচপি ম্যানুয়ালটিতে এটি খুঁজে পান: ফাস্টসিজিআই প্রসেস ম্যানেজার (এফপিএম) ; তবে সেই ফাংশনটি বিশেষভাবে ম্যানুয়ালটিতে আর নথিভুক্ত করা হয়নি। এখানে পিএইচপি-এফপিএম এর অংশ: পিএইচপি ফাস্টসিজিআই প্রক্রিয়া পরিচালক উইকি :


fastcgi_finish_request ()

সুযোগ: পিএইচপি ফাংশন

বিভাগ: অপ্টিমাইজেশন

এই বৈশিষ্ট্যটি আপনাকে কিছু পিএইচপি কোয়েরি প্রয়োগের গতি বাড়ানোর অনুমতি দেয়। স্ক্রিপ্ট কার্যকরকরণের প্রক্রিয়াতে ক্রিয়া রয়েছে যা সার্ভারের প্রতিক্রিয়াকে প্রভাবিত করে না Ac উদাহরণস্বরূপ, মেমক্যাচে সেশনটি সংরক্ষণ করা পৃষ্ঠাটি তৈরি হওয়ার পরে এবং একটি ওয়েব সার্ভারে পাস করার পরে ঘটতে পারে। fastcgi_finish_request()এটি একটি পিএইচপি বৈশিষ্ট্য, যা প্রতিক্রিয়া আউটপুট থামায়। ওয়েব সার্ভার তাত্ক্ষণিকভাবে ক্লায়েন্টের কাছে "ধীরে ধীরে এবং দুঃখের সাথে" প্রতিক্রিয়া স্থানান্তরিত করতে শুরু করে এবং পিএইচপি একই সাথে একটি ক্যোয়ারির প্রসঙ্গে অনেকগুলি দরকারী কাজ করতে পারে যেমন সেশন সংরক্ষণ করা, ডাউনলোড করা ভিডিও রূপান্তর করা, সমস্ত ধরণের পরিচালনা করা পরিসংখ্যান, ইত্যাদি

fastcgi_finish_request() শাটডাউন ফাংশন সম্পাদন করতে পারেন।


নোট: fastcgi_finish_request() হয়েছে একটি ছল যেখানে কল flush, printঅথবা echoগোড়ার দিকে স্ক্রিপ্ট বিনষ্ট হবে।

সমস্যাটি এড়াতে, আপনি কল করার ignore_user_abort(true)ঠিক আগে বা পরে কল করতে পারেন fastcgi_finish_request:

ignore_user_abort(true);
fastcgi_finish_request();

4
এটি বাস্তব উত্তর!
কিরিল টিটোভ

4
যদি আপনি পিএইচপি-এফপিএম ব্যবহার করে থাকেন - কেবলমাত্র এই ফাংশনটি ব্যবহার করুন - শিরোনাম এবং সমস্ত কিছু সম্পর্কে ভুলে যান। আমাকে এত সময় বাঁচিয়েছে!
রস

17

সম্পূর্ণ সংস্করণ:

ignore_user_abort(true);//avoid apache to kill the php running
ob_start();//start buffer output

echo "show something to user";
session_write_close();//close session file on server side to avoid blocking other requests

header("Content-Encoding: none");//send header to avoid the browser side to take content as gzip format
header("Content-Length: ".ob_get_length());//send length header
header("Connection: close");//or redirect to some url: header('Location: http://www.google.com');
ob_end_flush();flush();//really send content, can't change the order:1.ob buffer to normal buffer, 2.normal buffer to output

//continue do something on server side
ob_start();
sleep(5);//the user won't wait for the 5 seconds
echo 'for diyism';//user can't see this
file_put_contents('/tmp/process.log', ob_get_contents());
ob_end_clean();

কোন অর্থে সম্পূর্ণ? কোন সমস্যার জন্য আপনাকে গৃহীত উত্তর স্ক্রিপ্টটি সম্পূর্ণ করতে হবে (কোনটি?) এবং আপনার কোন কনফিগারেশন পার্থক্য এটি প্রয়োজনীয় করেছে?
hakre

4
এই লাইন: শিরোনাম ("সামগ্রী-এনকোডিং: কিছুই নয়"); -> খুব গুরুত্বপূর্ণ।
ববি টেবিলগুলি

4
ধন্যবাদ, এই পৃষ্ঠায় এটিই একমাত্র কার্যকরী সমাধান। এটি উত্তর হিসাবে অনুমোদিত করা উচিত।

6

একটি ভাল সমাধান একটি পটভূমি প্রক্রিয়া কাঁটাচামচ করা হয়। এটি ইউনিক্স / লিনাক্সে মোটামুটি সোজা এগিয়ে রয়েছে:

<?php
echo "We'll email you as soon as this is done.";
system("php somestuff.php dude@thatplace.com >/dev/null &");
?>

আরও ভাল উদাহরণগুলির জন্য আপনার এই প্রশ্নের দিকে নজর দেওয়া উচিত:

পিএইচপি একটি পটভূমি প্রক্রিয়া চালায়


4
আপনি যা করতে চান তা নির্ভর করে। যদি এটি কোনও ডেটা লিখতে থাকে, যা বর্তমান অনুরোধের সময় নির্ধারিত হয়েছিল, একটি ক্যাশে, তবে কাঁটাচামচ প্রায় নিশ্চিতভাবেই এর চেয়ে ভাল সমাধান নয়। এমনকি ওপি-র ক্ষেত্রেও, যদি অন্য সমাধানগুলি নির্ভরযোগ্য হয়, তবে তারা একটি জালযুক্ত প্রক্রিয়াতে উল্লেখযোগ্য পরিমাণে ডেটা পাস করার সাথে তুলনায় কিছু সার্ভার সিপিইউ চক্রকে ভালভাবে সাশ্রয় করতে পারে।
জেক

4

ধরে নিচ্ছি আপনার কাছে একটি লিনাক্স সার্ভার এবং রুট অ্যাক্সেস রয়েছে। এটি আমি খুঁজে পেয়েছি সবচেয়ে সহজ সমাধান।

নিম্নলিখিত ফাইলগুলির জন্য একটি নতুন ডিরেক্টরি তৈরি করুন এবং এটিকে সম্পূর্ণ অনুমতি দিন। (আমরা পরে এটি আরও সুরক্ষিত করতে পারি))

mkdir test
chmod -R 777 test
cd test

এটি একটি ফাইলের মধ্যে রাখুন bgping

echo starting bgping
ping -c 15 www.google.com > dump.txt &
echo ending bgping

নোট করুন &। বর্তমান প্রক্রিয়াটি ইকো কমান্ডে চলে যাওয়ার পরে পিং কমান্ডটি পটভূমিতে চলবে। এটি www.google.com কে 15 বার পিং করবে যা প্রায় 15 সেকেন্ড সময় নেবে।

এটি কার্যকর করা।

chmod 777 bgping

এটি একটি ফাইলের মধ্যে রাখুন bgtest.php

<?php

echo "start bgtest.php\n";
exec('./bgping', $output, $result)."\n";
echo "output:".print_r($output,true)."\n";
echo "result:".print_r($result,true)."\n";
echo "end bgtest.php\n";

?>

আপনি যখন আপনার ব্রাউজারে bgtest.php অনুরোধ করবেন, পিং কমান্ডটি শেষ হতে প্রায় 15 সেকেন্ড অপেক্ষা না করে আপনার নিম্নলিখিত প্রতিক্রিয়াটি দ্রুত পাওয়া উচিত।

start bgtest.php
output:Array
(
    [0] => starting bgping
    [1] => ending bgping
)

result:0
end bgtest.php

পিং কমান্ডটি এখন সার্ভারে চলমান উচিত। পিং কমান্ডের পরিবর্তে, আপনি পিএইচপি স্ক্রিপ্ট চালাতে পারেন:

php -n -f largejob.php > dump.txt &

আশাকরি এটা সাহায্য করবে!


4

টিম্বোর কোডটিতে একটি পরিবর্তন রয়েছে যা gzip সংক্ষেপণের সাথে কাজ করে।

// buffer all upcoming output
if(!ob_start("ob_gzhandler")){
    define('NO_GZ_BUFFER', true);
    ob_start();
}
echo "We'll email you as soon as this is done.";

//Flush here before getting content length if ob_gzhandler was used.
if(!defined('NO_GZ_BUFFER')){
    ob_end_flush();
}

// get the size of the output
$size = ob_get_length();

// send headers to tell the browser to close the connection
header("Content-Length: $size");
header('Connection: close');

// flush all output
ob_end_flush();
ob_flush();
flush();

// if you're using sessions, this prevents subsequent requests
// from hanging while the background process executes
if (session_id()) session_write_close();

/******** background process starts here ********/

আপনি একজন .শ্বর আমি এটি চেষ্টা করার জন্য 2 দিন ধরে কাজ করছি। এটি আমার স্থানীয় দেবের উপর কাজ করেছে তবে হোস্টে নয়। আমাকে হজ দেওয়া হয়েছিল। তুমি আমাকে রক্ষা করেছ. ধন্যবাদ!!!!
চাদ ক্যাল্ডওয়েল

3

আমি একটি শেয়ার্ড হোস্টে আছি এবং fastcgi_finish_requestসম্পূর্ণ স্ক্রিপ্ট থেকে প্রস্থান করার জন্য সেটআপ করছি। আমি connection: closeসমাধানটিও পছন্দ করি না । এটি ব্যবহার করে পরবর্তী অনুরোধগুলির জন্য একটি পৃথক সংযোগ জোর করে, অতিরিক্ত সার্ভার সংস্থানগুলি ব্যয় করে। আমি Transfer-Encoding: cunked উইকিপিডিয়া নিবন্ধটি পড়েছি এবং শিখেছি যা 0\r\n\r\nএকটি প্রতিক্রিয়া বন্ধ করে দেয়। আমি ব্রাউজারগুলির সংস্করণ এবং ডিভাইসগুলিতে এটি পুরোপুরি পরীক্ষা করে দেখিনি, তবে এটি আমার বর্তমান 4 টি ব্রাউজারে কাজ করে।

// Disable automatic compression
// @ini_set('zlib.output_compression', 'Off');
// @ini_set('output_buffering', 'Off');
// @ini_set('output_handler', '');
// @apache_setenv('no-gzip', 1);

// Chunked Transfer-Encoding & Gzip Content-Encoding
function ob_chunked_gzhandler($buffer, $phase) {
    if (!headers_sent()) header('Transfer-Encoding: chunked');
    $buffer = ob_gzhandler($buffer, $phase);
    return dechex(strlen($buffer))."\r\n$buffer\r\n";
}

ob_start('ob_chunked_gzhandler');

// First Chunk
echo "Hello World";
ob_flush();

// Second Chunk
echo ", Grand World";
ob_flush();

ob_end_clean();

// Terminating Chunk
echo "\x30\r\n\r\n";
ob_flush();
flush();

// Post Processing should not be displayed
for($i=0; $i<10; $i++) {
    print("Post-Processing");
    sleep(1);
}

আপনার উত্তরের উত্তরের জন্য ধন্যবাদ, আমি বুঝতে পেরেছি যে সংযোগটি ব্যবহার করা কতটা নির্বোধ (এবং অপ্রয়োজনীয়): বন্ধ। আমি অনুমান করি যে কিছু তাদের সার্ভারের বাদাম এবং বল্টের সাথে পরিচিত নয়।
জাস্টিন

@ জাস্টিন আমি এটি অনেক আগে লিখেছিলাম। এটি আবার দেখার জন্য, আমার মনে রাখা উচিত যে খণ্ডগুলি 4KB এ প্যাড করা প্রয়োজন হতে পারে। আমি মনে করি মনে হচ্ছে যে কিছু সার্ভারগুলি সর্বনিম্ন পৌঁছানো পর্যন্ত ফ্লাশ হবে না।
স্কিবুল্ক

@ এসকিবুল্ক কারও কারও জন্য 64 কে (সংকোচিত ??) প্যাডিং প্রয়োজন, যেমন এটি এফসিজিডআউটপুটবাফারসাইজের জন্য ডিফল্ট এবং কিছু ভাগ করা সার্ভারগুলিতে ওভাররাইড করা যায় না।
জেক

2

আপনি মাল্টিথ্রেডিং করার চেষ্টা করতে পারেন।

আপনি কোনও স্ক্রিপ্ট চাবুক করতে পারেন যা সিস্টেম কল করে ( শেল_এক্সেক ব্যবহার করে ) যা আপনার পরামিতি হিসাবে কাজ করতে স্ক্রিপ্টের সাথে পিএইচপি বাইনারি বলে। তবে আমি মনে করি না এটি সবচেয়ে সুরক্ষিত উপায়। হতে পারে আপনি পিএইচপি প্রক্রিয়া এবং অন্যান্য স্টাফ ক্রুট করে স্টাফ আঁকতে পারেন

বিকল্পভাবে, পিএইচপিচ্ল্যাসে একটি শ্রেণি রয়েছে যা এটি http://www.phpclasses.org/browse/package/3953.html করে । তবে বাস্তবায়নের সুনির্দিষ্ট বিবরণ আমি জানি না


এবং যদি আপনি প্রক্রিয়াটি শেষ হওয়ার জন্য অপেক্ষা করতে না চান &তবে ব্যাকগ্রাউন্ডে প্রক্রিয়াটি চালানোর জন্য অক্ষরটি ব্যবহার করুন ।
লিয়াম

2

টিএল; ডিআর উত্তর:

ignore_user_abort(true); //Safety measure so that the user doesn't stop the script too early.

$content = 'Hello World!'; //The content that will be sent to the browser.

header('Content-Length: ' . strlen($content)); //The browser will close the connection when the size of the content reaches "Content-Length", in this case, immediately.

ob_start(); //Content past this point...

echo $content;

//...will be sent to the browser (the output buffer gets flushed) when this code executes.
ob_end_flush();
ob_flush();
flush();

if(session_id())
{
    session_write_close(); //Closes writing to the output buffer.
}

//Anything past this point will be ran without involving the browser.

কার্য উত্তর:

ignore_user_abort(true);

function sendAndAbort($content)
{
    header('Content-Length: ' . strlen($content));

    ob_start();

    echo $content;

    ob_end_flush();
    ob_flush();
    flush();
}

sendAndAbort('Hello World!');

//Anything past this point will be ran without involving the browser.

1

পিএইচপি তে কিছু সমান্তরাল প্রোগ্রামিং করে আপনার সমস্যার সমাধান করা যেতে পারে। আমি কয়েক সপ্তাহ আগে এখানে এটি সম্পর্কে একটি প্রশ্ন জিজ্ঞাসা করেছি: পিএইচপি অ্যাপ্লিকেশনগুলিতে কেউ কীভাবে মাল্টি থ্রেডিং ব্যবহার করতে পারে

এবং দুর্দান্ত উত্তর পেয়েছে। আমি বিশেষভাবে একটি খুব পছন্দ। লেখক পিএইচপি-ইজি প্যারালাল প্রসেসিংয়ের বিষয়ে একটি উল্লেখ করেছেন (সেপ্টেম্বর ২০০৮; জনলিম দ্বারা) টিউটোরিয়াল যা আপনার সমস্যাটি খুব ভালভাবে সমাধান করতে পারে যেমন আমি কয়েক দিন আগে এ জাতীয় সমস্যাটি মোকাবিলা করতে ইতিমধ্যে এটি ব্যবহার করেছি।


1

জোয়েরি সেব্রেচটসের উত্তরটি নিকটে, তবে এটি সংযোগ বিচ্ছিন্ন করতে ইচ্ছুক হওয়ার আগে এটি যে কোনও বিদ্যমান সামগ্রী বাফার হতে পারে তা ধ্বংস করে দেয়। এটি ঠিকমতো কল করে না ignore_user_abort, স্ক্রিপ্টটি অকালে শেষ করতে দেয়। ডায়াইজমের উত্তর ভাল তবে সাধারণভাবে প্রযোজ্য নয়। উদাহরণস্বরূপ একজন ব্যক্তির বৃহত্তর বা কম আউটপুট বাফার থাকতে পারে যা উত্তরটি হ্যান্ডেল করে না, সুতরাং এটি আপনার পরিস্থিতিতে সহজভাবে কাজ করতে পারে না এবং কেন আপনি তা জানতে পারবেন না।

এই ফাংশনটি আপনাকে যে কোনও সময় সংযোগ বিচ্ছিন্ন করার অনুমতি দেয় (যতক্ষণ না শিরোনামগুলি এখনও প্রেরণ করা হয়নি) এবং আপনি এখন পর্যন্ত যে সামগ্রী তৈরি করেছেন তা ধরে রাখে। অতিরিক্ত প্রক্রিয়াকরণের সময়টি ডিফল্টরূপে সীমাহীন।

function disconnect_continue_processing($time_limit = null) {
    ignore_user_abort(true);
    session_write_close();
    set_time_limit((int) $time_limit);//defaults to no limit
    while (ob_get_level() > 1) {//only keep the last buffer if nested
        ob_end_flush();
    }
    $last_buffer = ob_get_level();
    $length = $last_buffer ? ob_get_length() : 0;
    header("Content-Length: $length");
    header('Connection: close');
    if ($last_buffer) {
        ob_end_flush();
    }
    flush();
}

আপনার যদি অতিরিক্ত মেমরির প্রয়োজন হয় তবে এই ফাংশনটি কল করার আগে এটি বরাদ্দ করুন।


1

Mod_fcgid ব্যবহারকারীদের জন্য নোট (দয়া করে, আপনার নিজের ঝুঁকিতে ব্যবহার করুন)।

দ্রুত সমাধান

জোয়েরি সেব্রেচটসের গৃহীত উত্তরটি আসলে কার্যকরী। তবে আপনি যদি mod_fcgid ব্যবহার করেন তবে আপনি দেখতে পাবেন যে এই সমাধানটি নিজে থেকে কাজ করে না। অন্য কথায়, ফ্লাশ যখন ফাংশন বলা হয় তখন ক্লায়েন্টের সাথে সংযোগ বন্ধ হয় না।

FcgidOutputBufferSizeকনফিগারেশন প্যারামিটার mod_fcgid দায়ী করা যেতে পারে। আমি এই টিপটি পেয়েছি:

  1. ট্র্যাভার্স কার্টার এবং এই উত্তর
  2. Seumas ম্যাকিনন এই ব্লগ পোস্ট

উপরেরটি পড়ার পরে, আপনি এই সিদ্ধান্তে আসতে পারেন যে একটি দ্রুত সমাধান হ'ল লাইন যুক্ত করা (শেষে "ভার্চুয়াল হোস্টের উদাহরণ দেখুন"):

FcgidOutputBufferSize 0

আপনার অ্যাপাচি কনফিগারেশন ফাইল (যেমন, httpd.conf), আপনার FCGI কনফিগারেশন ফাইল (যেমন, fcgid.conf) অথবা আপনার ভার্চুয়াল হোস্ট ফাইলের মধ্যে (যেমন, httpd-vhosts.conf)।

উপরের (1) এ, "আউটপুটবফারসাইজ" নামের একটি পরিবর্তনশীল উল্লেখ করা হয়েছে। এটি FcgidOutputBufferSize(2) এ উল্লিখিত পুরানো নাম ( Mod_fcgid এর জন্য অ্যাপাচি ওয়েব পৃষ্ঠায় আপগ্রেড নোটগুলি দেখুন )।

বিশদ ও দ্বিতীয় সমাধান

উপরের সমাধানটি mod_fcgid দ্বারা সম্পাদিত বাফারিং অক্ষম করে পুরো সার্ভারের জন্য বা নির্দিষ্ট ভার্চুয়াল হোস্টের জন্য । এটি আপনার ওয়েবসাইটের জন্য পারফরম্যান্স জরিমানার দিকে নিয়ে যেতে পারে। অন্যদিকে, পিএইচপি নিজে থেকে বাফারিং করে এমনটি নাও হতে পারে।

আপনি যদি mod_fcgid এর বাফারিংটি অক্ষম করতে না চান তবে অন্য একটি সমাধান আছে ... আপনি এই বাফারটিকে ফ্লাশ করতে বাধ্য করতে পারেন

জোয়ারি সেব্রেক্টস প্রস্তাবিত সমাধানটির উপর ভিত্তি করে নীচের কোডটি কেবল এটি করে:

<?php
    ob_end_clean();
    header("Connection: close");
    ignore_user_abort(true); // just to be safe
    ob_start();
    echo('Text the user will see');

    echo(str_repeat(' ', 65537)); // [+] Line added: Fill up mod_fcgi's buffer.

    $size = ob_get_length();
    header("Content-Length: $size");
    ob_end_flush(); // Strange behaviour, will not work
    flush(); // Unless both are called !
    // Do processing here 
    sleep(30);
    echo('Text user will never see');
?>

কোডের যুক্ত লাইনটি মূলত যা করে তা হ'ল Mod_fcgi এর বাফারটি পূরণ করা , এটি এটিকে ফ্লাশ করতে বাধ্য করে। নম্বর "65537" মনোনীত করা হয়েছে কারণ ডিফল্ট মান FcgidOutputBufferSizeপরিবর্তনশীল "65536" হয়, যেমন উল্লেখ সংশ্লিষ্ট নির্দেশ জন্য Apache ওয়েব পৃষ্ঠা । সুতরাং, আপনার পরিবেশে অন্য মান সেট করা থাকলে সেই অনুযায়ী আপনার এই মানটি সামঞ্জস্য করতে হবে।

আমার পরিবেশ

  • ওয়্যাম্প সার্ভার 2.5
  • অ্যাপাচি ২.৪.৯
  • পিএইচপি 5.5.19 ভিসি 11, x86, নন থ্রেড নিরাপদ
  • mod_fcgid / 2.3.9
  • উইন্ডোজ 7 পেশাদার x64

ভার্চুয়াল হোস্টের উদাহরণ

<VirtualHost *:80>
    DocumentRoot "d:/wamp/www/example"
    ServerName example.local

    FcgidOutputBufferSize 0

    <Directory "d:/wamp/www/example">
        Require all granted
    </Directory>
</VirtualHost>

আমি অনেক সমাধান চেষ্টা করেছিলাম। এবং Mod_fcgid নিয়ে আমার জন্য কাজ করা এটিই একমাত্র সমাধান।
সসনাবে

1

এটি আমার জন্য কাজ করেছে

//avoid apache to kill the php running
ignore_user_abort(true);
//start buffer output
ob_start();

echo "show something to user1";
//close session file on server side to avoid blocking other requests
session_write_close();

//send length header
header("Content-Length: ".ob_get_length());
header("Connection: close");
//really send content, can't change the order:
//1.ob buffer to normal buffer,
//2.normal buffer to output
ob_end_flush();
flush();
//continue do something on server side
ob_start();
//replace it with the background task
sleep(20);

0

ঠিক আছে, তাই মূলত jQuery XHR কে অনুরোধ করে, এমনকি ob_flush পদ্ধতিটিও কাজ করবে না কারণ আপনি প্রতিটি অনডিস্টেটচেঞ্জে কোনও ক্রিয়াকলাপ চালাতে অক্ষম। jQuery রাষ্ট্র পরীক্ষা করে, তারপরে যথাযথ পদক্ষেপগুলি বেছে নেয় (সম্পূর্ণ, ত্রুটি, সাফল্য, সময়সীমা)। এবং যদিও আমি কোনও রেফারেন্স সন্ধান করতে অক্ষম ছিলাম, শুনলাম মনে পড়ে যে এটি সমস্ত এক্সএইচআর বাস্তবায়নের সাথে কাজ করে না। এমন একটি পদ্ধতি যা আমি বিশ্বাস করি যে আপনার জন্য কাজ করা উচিত তা হল __ফ্লুশ এবং চিরকালের ফ্রেম ভোটদানের মধ্যে একটি ক্রস।

<?php
 function wrap($str)
 {
  return "<script>{$str}</script>";
 };

 ob_start(); // begin buffering output
 echo wrap("console.log('test1');");
 ob_flush(); // push current buffer
 flush(); // this flush actually pushed to the browser
 $t = time();
 while($t > (time() - 3)) {} // wait 3 seconds
 echo wrap("console.log('test2');");
?>

<html>
 <body>
  <iframe src="ob.php"></iframe>
 </body>
</html>

এবং স্ক্রিপ্টগুলি ইনলাইন সম্পাদন করার কারণে, যেমন বাফারগুলি সজ্জিত করা হয়, আপনি কার্যকর হন। এটি দরকারী করতে, কনসোল.লগ পরিবর্তন করে ডেটা গ্রহণ এবং এটিতে কাজ করতে আপনার মূল স্ক্রিপ্ট সেটআপে সংজ্ঞায়িত কলব্যাক পদ্ধতিতে। আশাকরি এটা সাহায্য করবে. চিয়ার্স, মরগান


0

বিকল্প সমাধান হ'ল চাকরিতে একটি কাতারে যুক্ত করা এবং ক্রোন স্ক্রিপ্ট তৈরি করা যা নতুন কাজের জন্য পরীক্ষা করে এবং সেগুলি চালায়।

একটি শেয়ার্ড হোস্ট দ্বারা আরোপিত সীমাটি সীমাবদ্ধ করার জন্য আমাকে সম্প্রতি সেভাবে এটি করতে হয়েছিল - এক্সিকিউটিভ () এবং আল ওয়েব সার্ভার দ্বারা চালিত পিএইচপি-র জন্য অক্ষম করা হয়েছিল তবে শেল স্ক্রিপ্টে চালাতে পারে।


0

যদি flush()ফাংশনটি কাজ করে না। আপনার অবশ্যই পরবর্তী বিকল্পগুলি php.ini এ সেট করতে হবে :

output_buffering = Off  
zlib.output_compression = Off  

0

সর্বশেষ কার্যনির্বাহী সমাধান

    // client can see outputs if any
    ignore_user_abort(true);
    ob_start();
    echo "success";
    $buffer_size = ob_get_length();
    session_write_close();
    header("Content-Encoding: none");
    header("Content-Length: $buffer_size");
    header("Connection: close");
    ob_end_flush();
    ob_flush();
    flush();

    sleep(2);
    ob_start();
    // client cannot see the result of code below

0

এই থ্রেড থেকে বহুবিধ সমাধানের চেষ্টা করার পরে (তাদের কেউই আমার পক্ষে কাজ না করার পরে), আমি অফিসিয়াল পিএইচপি.নেট পৃষ্ঠায় সমাধান পেয়েছি:

function sendResponse($response) {
    ob_end_clean();
    header("Connection: close\r\n");
    header("Content-Encoding: none\r\n");
    ignore_user_abort(true);
    ob_start();

    echo $response; // Actual response that will be sent to the user

    $size = ob_get_length();
    header("Content-Length: $size");
    ob_end_flush();
    flush();
    if (ob_get_contents()) {
        ob_end_clean();
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.