পাইথনের সকেট recv পদ্ধতিতে কীভাবে সময়সীমা সেট করবেন?


110

পাইথনের সকেট recv পদ্ধতিতে আমার সময়সীমা নির্ধারণ করতে হবে। এটা কিভাবে করতে হবে?


2
এফওয়াইআই যদি আপনি টাইমআউটগুলি ব্যবহার করা চয়ন করেন ... টাইমআউটটি কীভাবে পরিচালনা করতে হবে তা আপনার জানতে হবে। সময়সীমা শেষ হওয়ার পরে এই পরিচালনা প্রশ্নটি হ্যান্ডলিং সম্পর্কে কথা বলে: স্ট্যাকওভারফ্লো
ট্রেভর বয়ড স্মিথ

উত্তর:


125

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

import select

mysocket.setblocking(0)

ready = select.select([mysocket], [], [], timeout_in_seconds)
if ready[0]:
    data = mysocket.recv(4096)

আপনার যদি অনেকগুলি মুক্ত ফাইল বর্ণনাকারী থাকে তবে পোল () এর আরও কার্যকর বিকল্প select()

অন্য বিকল্পটি ব্যবহার করে সকেটের সমস্ত ক্রিয়াকলাপের জন্য সময়সীমা নির্ধারণ করা হয় socket.settimeout()তবে আমি দেখতে পাচ্ছি যে আপনি অন্য উত্তরে সেই সমাধানটি স্পষ্টভাবে প্রত্যাখ্যান করেছেন।


16
ব্যবহার selectভাল, তবে যে অংশটি আপনি "আপনি পারবেন না" বলছেন তা বিভ্রান্তিমূলক, কারণ রয়েছে socket.settimeout()
nosklo

1
এটি এখন আরও ভাল তবে উত্তরটি "স্পষ্টতই প্রত্যাখ্যান করা" হয়েছিল তা আমি দেখতে পাচ্ছি না।
nosklo

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

4
কেন সকেটটি কোনও অ-ব্লকিং সেট করা প্রয়োজন? আমি মনে করি না যে নির্বাচিত কলটি (এবং কোনও বর্ণনাকারী পড়তে না পারা বা এই ক্ষেত্রে সময়সীমা সমাপ্ত হওয়া অবধি এটি ব্লক করে) এবং নির্বাচনটি সন্তুষ্ট হলে রিক () ব্লক করবে না। আমি এটি recvfrom () ব্যবহার করে চেষ্টা করেছি এবং মনে হচ্ছে সেটব্লকিং (0) ছাড়াই এটি সঠিকভাবে কাজ করবে।
হ্যাঙ্কবি

1
চান ready[0]শুধুমাত্র মিথ্যা হতে যদি সার্ভারের প্রতিক্রিয়া কোন শরীর?
ম্যাটানস্টার

60

সেখানে socket.settimeout()


16
এটি পুনরুদ্ধারের সময়সীমা অতিক্রম করে না (অন্তত আমি চেষ্টা করার পরে)। কেবল গ্রহণ () এর সময়সীমা শেষ।
ওরেেন এস

9
Socket.recv () সকেট.সেটটাইমআউট () সেট করার পরে ঠিক ঠিক মত ঠিক হয়ে গেছে বলে মনে হচ্ছে। আমি কি এটি তৈরি করছি? অন্য কেউ এটি নিশ্চিত করতে পারেন?
এনিওট

3
@ এওনাউত আমি মনে করি যে এই সময়টি বেশিরভাগ সময় পুনঃসংশ্লিষ্ট হয় (তবে) একটি রেসের শর্ত রয়েছে। সকেট.রেসিভিতে () পাইথন (২.6) কালআউট সহ অভ্যন্তরীণভাবে সিলেক্ট / পোল কল করে এবং তারপরেই পুনরায় () ডাকা হয়। সুতরাং যদি আপনি একটি ব্লকিং সকেট ব্যবহার করেন এবং এই 2 টির মধ্যে অন্য শেষ পয়েন্ট ক্র্যাশ হয় তবে আপনি পুনরায় () এ অনির্দিষ্টকালের জন্য ঝুলিয়ে রাখতে পারেন। যদি আপনি অ-ব্লকিং সকেট ব্যবহার করেন, অজগরটি সিলেক্ট করুন না intern অভ্যন্তরীণভাবে নির্বাচন করুন, তাই আমার মনে হয় ড্যানিয়েল স্টুটজবাচের উত্তরটি সঠিক উপায়।
emil.p.stanchev

4
প্রকৃতপক্ষে, () প্রত্যাবর্তন করার সময় আমি সম্ভবত ভুল বুঝেছিলাম, সুতরাং দয়া করে পূর্ববর্তী মন্তব্যটি স্ক্র্যাচ করুন। বিজের গাইড বলেছে উপরেরটি পুনঃনির্ধারণের সময়সীমা কার্যকর করার একটি বৈধ উপায়: beej.us/guide/bgnet/output/html/singlepage/… সুতরাং আমি বিশ্বাস করি এটি একটি লেখক উত্স।
emil.p.stanchev

2
আমি নিশ্চিত না যে কেন এই selectদ্রবণটি যখন ওয়ান লাইনার (বজায় রাখা সহজ, ভুল প্রয়োগের ক্ষেত্রে কম ঝুঁকি থাকে) এবং হুডের নীচে নির্বাচনগুলি ব্যবহার করে তবে যে সমাধানটি ব্যবহার করা হয় সেটিকে কেন অগ্রাধিকার দেওয়া হয় (বাস্তবায়ন @ ড্যানিয়েল স্টুজবাচের উত্তর হিসাবে একই)।
ট্রেভর বয়েড স্মিথ

33

উভয় উল্লিখিত select.select()এবং socket.settimeout()কাজ করবে।

নোট করুন আপনার প্রয়োজনের জন্য আপনাকে settimeoutদুবার কল করার প্রয়োজন হতে পারে , যেমন

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("",0))
sock.listen(1)
# accept can throw socket.timeout
sock.settimeout(5.0)
conn, addr = sock.accept()

# recv can throw socket.timeout
conn.settimeout(5.0)
conn.recv(1024)

3
আমি মনে করি তিনি যেখানে রয়েছেন ঠিক তেমনই আমি সেখানে আছি যেখানে আপনি এই ফাংশনটি কীভাবে ঝুলিয়ে দিচ্ছেন এবং তা ঝুলিয়ে দেওয়া কোনও ব্যাপার নয়। আমি এখন 2 বা 4 টাইমআউট চেষ্টা করেছি এবং এটি এখনও স্তব্ধ। সেটটাইম আউট হয়ে যায়।
কেসি ড্যানিয়েল

1
আপনি .settimeout()একাধিকবার কল করার সময় আপনি setdefaulttimeout()পদ্ধতিটিকে প্রথম স্থানে কল করতে পারেন ।
mvarge

12

প্রতিক্রিয়া পাওয়ার আগে এবং প্রতিক্রিয়া পাওয়ার পরে আপনি টাইমআউট সেট করতে পারেন কোনওটিতে সেট করে না:

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

sock.settimeout(5.0)
data = sock.recv(1024)
sock.settimeout(None)

5

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

sock.listen(1)
connection, client_address = sock.accept()
connection.settimeout(5)    # This is the one that affects recv() method.
connection.gettimeout()     # This should result 5
sock.gettimeout()           # This outputs None when not set previously, if I remember correctly.

আপনি যদি ক্লায়েন্ট পক্ষটি বাস্তবায়ন করেন তবে এটি সহজ হবে।

sock.connect(server_address)
sock.settimeout(3)

2

পূর্ববর্তী উত্তরে উল্লিখিত হিসাবে, আপনি এর মতো কিছু ব্যবহার করতে পারেন: .settimeout() উদাহরণস্বরূপ:

import socket

s = socket.socket()

s.settimeout(1) # Sets the socket to timeout after 1 second of no activity

host, port = "somehost", 4444
s.connect((host, port))

s.send("Hello World!\r\n")

try:
    rec = s.recv(100) # try to receive 100 bytes
except socket.timeout: # fail after 1 second of no activity
    print("Didn't receive data! [Timeout]")
finally:
    s.close()

আশা করি এটা কাজে লাগবে!!


2

আপনি ব্যবহার করতে পারেন socket.settimeout()যা সেকেন্ডের সংখ্যার প্রতিনিধিত্ব করে একটি পূর্ণসংখ্যার যুক্তি গ্রহণ করে। উদাহরণস্বরূপ, socket.settimeout(1)সময়সীমাটি 1 সেকেন্ডে সেট করবে


2

এটি অন্তর্নিহিত সি ব্যবহার করে দেখুন

timeval = struct.pack('ll', 2, 100)
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, timeval)

এই মহান যেমন পাঠাতে এবং recv সময়সীমার ব্যবহার করার জন্য বিভিন্ন মান নির্ধারণ করেন এক পারবেন SO_RCVTIMEOএবং SO_SNDTIMEO
jtpereyda

কেন 2এবং কেন 100? সময়সীমা মান কোনটি? কোন ইউনিটে?
আলফ

timeval = struct.pack('ll', sec, usec) s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, timeval)usec = 10000 এর অর্থ 10 এমএস
নৌবাহিনী

1
#! /usr/bin/python3.6

# -*- coding: utf-8 -*-
import socket
import time
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.settimeout(5)
PORT = 10801

s.bind(('', PORT))
print('Listening for broadcast at ', s.getsockname())
BUFFER_SIZE = 4096
while True:
    try:
        data, address = s.recvfrom(BUFFER_SIZE)
    except socket.timeout:
        print("Didn't receive data! [Timeout 5s]")
        continue

0

চিৎকার করে দেখুন: https://boltons.readthedocs.io/en/latest/sketutils.html

এটি একটি বাফারযুক্ত সকেট সরবরাহ করে, এটি প্রচুর দরকারী কার্যকারিতা যেমন:

.recv_until()    #recv until occurrence of bytes
.recv_closed()   #recv until close
.peek()          #peek at buffer but don't pop values
.settimeout()    #configure timeout (including recv timeout)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.