লিনাক্স: টাইম আউট সহ সকেট থেকে একটি পঠিত বা recv আছে?


105

টাইম আউট সহ আমি কীভাবে সকেট থেকে ডেটা পড়ার চেষ্টা করতে পারি? আমি জানি, নির্বাচন করুন, সিলেক্ট করুন, পোল করুন, একটি টাইমআউট ক্ষেত্র রয়েছে, তবে সেগুলি ব্যবহার করে টিসিপি রেনো স্ট্যাকের "টিসিপি ফাস্ট-পাথ" অক্ষম করে।

আমার কাছে একমাত্র ধারণাটি হ'ল একটি লুপে রিক (এফডি, ..., এমএসজি_ডন্টওয়াট) ব্যবহার করা


থ্রেডগুলি ব্যবহার করার একটি বিকল্পও রয়েছে :) তবে থ্রেড সংকেতগুলি এখনও দরকার
osgx

উত্তর:


189

ক্রিয়াকলাপ গ্রহণের সময়সীমা নির্ধারণ করতে আপনি সেটসোক্ট ফাংশনটি ব্যবহার করতে পারেন :

SO_RCVTIMEO

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

// LINUX
struct timeval tv;
tv.tv_sec = timeout_in_seconds;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);

// WINDOWS
DWORD timeout = timeout_in_seconds * 1000;
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof timeout);

// MAC OS X (identical to Linux)
struct timeval tv;
tv.tv_sec = timeout_in_seconds;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);

রিপোর্টে উইন্ডোজ এ কল করার আগে করা উচিত bind। আমি পরীক্ষার মাধ্যমে যাচাই করেছি যে এটি bindলিনাক্স এবং ওএস এক্স এর আগে বা পরে করা যেতে পারে ।


1
এই উত্তরটি আমার পাছা বাঁচিয়েছে। আমি কোনও সাফল্য না পেয়ে এই সংশ্লেষিত "নির্বাচন করুন" বকাবকি বাস্তবায়নে আটকে ছিলাম। এটি অবিলম্বে কাজ করেছে, এত সহজ।
মিলোডিসি

এখন সে কারণেই উইন্ডোতে টাইমআউট কাজ করছে না কারণ আমি লিনাক্সের জন্য কোডটি ব্যবহার করছি। ধন্যবাদ। উইন্ডোজ যদি ব্যবহার না করে struct timeval tv;তবে এর অর্থ কি নির্বাচন () খুব বেশি কাজ করবে না? আমি আমার সিলেক্ট () কোডটি উইন্ডোগুলিতে পোর্ট করার চেষ্টা করেছি এবং অবিলম্বে এটির সময়সামগ্রীটি দেখে মনে হচ্ছে এটি সময়ের সাথে আমি যে মানটি নির্ধারণ করছি তা উপেক্ষা করছে।
কুচি

1
আমি টাইমআউট মান 5 সেকেন্ডে সেট করেছিলাম। ইনকামিং ডেটা থাকুক বা না থাকুক কেন প্রতিটি পঠন চক্রের জন্য সর্বদা 5 সেকেন্ড সময় লাগে?
হান

এটি বাইন্ড অপারেশনের পরেও উইন্ডোতে কাজ করে। উইন্ডোজ 10
cahit beyaz

1
@ user463035818 এই উত্তর দাবি করে যে এটি করা উচিত নয়।
টোমিয়ামিস

22

সি recvব্যবহার করে আপনার ফাংশনটিতে একটি সময় যোগ করার জন্য কয়েকটি সাধারণ কোড এখানে রয়েছে poll:

struct pollfd fd;
int ret;

fd.fd = mySocket; // your socket handler 
fd.events = POLLIN;
ret = poll(&fd, 1, 1000); // 1 second for timeout
switch (ret) {
    case -1:
        // Error
        break;
    case 0:
        // Timeout 
        break;
    default:
        recv(mySocket,buf,sizeof(buf), 0); // get your data
        break;
}

এটি প্রত্যাশার মতো ঠিক কাজ করবে না। pollকমপক্ষে একটি বাইট বা টাইমআউট পাওয়ার জন্য অপেক্ষা করবে, যেখানে recvফাংশনটি কল করার সময় এটি sizeof(buf)বাইটের জন্য অপেক্ষা করবে , যদি এই গণনাটি এখনও না পৌঁছায় তবে এটি আবার ব্লক হয়ে যাবে, তবে এবার সময়সীমা ছাড়াই।
LoPiTaL

0

// উইন্ডোগুলির জন্য বাইন্ড অপারেশনের পরেও কাজ করে

DWORD timeout = timeout_in_seconds * 1000;
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof timeout);

-1

একটি নিয়ন্ত্রক ইনস্টল SIGALRMকরুন, তারপরে alarm()বা ualarm()একটি নিয়মিত ব্লক সামনে recv()। অ্যালার্ম বন্ধ হয়ে গেলে, সেটটি সেট করে recv()একটি ত্রুটি ফিরে আসবে ।errnoEINTR


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

2
@osgx সময়সীমা শেষ হলেই সিগন্যালটি ঘটে।
ডেভিড শোয়ার্টজ

-4

লিনাক্স

struct timeval tv;
tv.tv_sec = 30;        // 30 Secs Timeout
tv.tv_usec = 0;        // Not init'ing this can cause strange errors
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv,sizeof(struct timeval));

উইন্ডোজ

DWORD timeout = SOCKET_READ_TIMEOUT_SEC * 1000;
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));

দ্রষ্টব্য : আপনি bind()সঠিক রান করার জন্য ফাংশন কল করার আগে এই সেটিংটি রেখে দিয়েছেন


4
এই প্রশ্নের উত্তর ইতিমধ্যে কয়েক বছর আগে দেওয়া হয়েছে। আপনার সমাধানটি কোন নতুন মূল্য নিয়ে আসে?
ম্যাকিয়েজ জুরেসকো

আপনি এই সেটিংটি বাইন্ডের আগে রেখে দিয়েছেন () ফাংশন কলটি যথাযথভাবে চালানোর জন্য এই অংশটির
বিবেক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.