การตั้งค่าการหมดเวลาสำหรับการทำงานของซ็อกเก็ต


87

เมื่อฉันสร้างซ็อกเก็ต:

Socket socket = new Socket(ipAddress, port);

มันแสดงข้อยกเว้นซึ่งก็โอเคเนื่องจากไม่มีที่อยู่ IP (ตัวแปรทดสอบที่String ipAddress = "192.168.0.3"และint port = 300.)

ปัญหาคือ: ฉันจะตั้งค่าให้หมดเวลาสำหรับซ็อกเก็ตนั้นได้อย่างไร?

เมื่อฉันสร้างซ็อกเก็ตฉันจะลดเวลาก่อนที่ฉันจะได้รับUnknownHostExceptionและทำให้ซ็อกเก็ตหมดเวลาได้อย่างไร


10
@adrianboimvaser: ในกรณีนี้คุณควรตั้งค่าสถานะว่าซ้ำกันและแสดงความคิดเห็นที่ชี้ไปที่รายการที่ซ้ำกันเพื่อให้ผู้ดูแลสามารถปิดได้ (คุณแสดงความคิดเห็นนั้นไว้เมื่อปีที่แล้ว - บางทีคุณอาจจะรู้แล้วในตอนนี้) ฉันจะโหวตให้ทำตอนนี้ แต่ฉันไม่รู้ว่ารายการซ้ำอยู่ที่ไหน!
Tom Anderson

1
เพื่อให้แนวโน้มของการตอบกลับล่าช้าหลายปี @EJP ชื่อของคำถามนี้มีความคลุมเครือน้อยกว่าคำถามที่คุณแนะนำ
Isaac

@Isaac และในความเป็นจริงมันไม่ซ้ำกันเลยลบความคิดเห็น
user207421

(หมายเหตุ: ฉันได้ปรับแต่ง tittle ให้คลุมเครือน้อยลง)
Stephen C

คำตอบ:


167

ใช้ตัวSocket()สร้างและconnect(SocketAddress endpoint, int timeout)วิธีการแทน

ในกรณีของคุณจะมีลักษณะดังนี้:

Socket socket = new Socket();
socket.connect(new InetSocketAddress(ipAddress, port), 1000);

อ้างจากเอกสาร

connect

public void connect(SocketAddress endpoint, int timeout) throws IOException

เชื่อมต่อซ็อกเก็ตนี้กับเซิร์ฟเวอร์ด้วยค่าการหมดเวลาที่ระบุ การหมดเวลาเป็นศูนย์ถูกตีความว่าเป็นการหมดเวลาที่ไม่มีที่สิ้นสุด จากนั้นการเชื่อมต่อจะบล็อกจนกว่าจะสร้างได้หรือเกิดข้อผิดพลาด

พารามิเตอร์:

endpoint- SocketAddress
timeout- ค่าการหมดเวลาที่จะใช้ในหน่วยมิลลิวินาที

พ่น:

IOException- หากเกิดข้อผิดพลาดระหว่างการเชื่อมต่อ
SocketTimeoutException- หากหมดเวลาก่อนที่จะเชื่อมต่อ
IllegalBlockingModeException- หากซ็อกเก็ตนี้มีช่องสัญญาณที่เกี่ยวข้องและช่องสัญญาณอยู่ในโหมดไม่ปิดกั้น
IllegalArgumentException- หากจุดสิ้นสุดเป็นค่าว่างหรือเป็นคลาสย่อย SocketAddress ที่ซ็อกเก็ตนี้ไม่รองรับ

ตั้งแต่: 1.4


4
สิ่งนี้สามารถลดระยะหมดเวลาสำหรับ ConnectException (แต่ไม่เพิ่มขึ้น) และไม่มีผลต่อการหมดเวลาสำหรับ UnknownHostException ซึ่ง OP อ้างว่าเขาได้รับ (แม้ว่าฉันจะไม่เชื่อก็ตาม) โปรดทราบด้วยว่า Javadoc ไม่ถูกต้องในการระบุว่าค่าเริ่มต้นคืออินฟินิตี้ มันไม่ใช่ แพลตฟอร์มมีระยะหมดเวลาเริ่มต้นประมาณหนึ่งนาทีและไม่สามารถเพิ่มได้
user207421

3
แม้จะผ่านไป 4 ปี แต่สิ่งนี้ก็น่าจะเป็นคำตอบที่ยอมรับได้
คมชัดลึก

4
ตอนนี้ผ่านไป 5 ปีแล้วและเป็นคำตอบที่ดีที่สุดที่ฉันพบบนอินเทอร์เน็ต .. ขอบคุณ
MBH

1
สิ่งสำคัญคือต้องเรียกsocket.setSoTimeout(timeoutMillis)ให้หมดเวลาระหว่างการบล็อกการดำเนินการ IO
Grey

43

คุณไม่ได้กำหนดระยะหมดเวลาสำหรับซ็อกเก็ตคุณกำหนดระยะหมดเวลาสำหรับการดำเนินการที่คุณดำเนินการกับซ็อกเก็ตนั้น

ตัวอย่างเช่น socket.connect(otherAddress, timeout)

หรือsocket.setSoTimeout(timeout)สำหรับการตั้งค่าการหมดเวลาในread()การดำเนินการ

ดู: http://docs.oracle.com/javase/7/docs/api/java/net/Socket.html


ในกรณีนี้มันเป็นการดำเนินการเชื่อมต่อ ฉันไม่พบสถานที่ใด ๆ ที่ระบุว่า ctor นี้ใช้การหมดเวลาที่ไม่สิ้นสุดแม้ว่าจะเป็นเช่นนั้นก็ตาม
sandos

3
@sandos มีระบุไว้ชัดเจนใน Javadoc สำหรับการเชื่อมต่อ () อย่างไรก็ตามมันก็ไม่ถูกต้องเช่นกัน การหมดเวลาเริ่มต้นคือการหมดเวลาของแพลตฟอร์มประมาณหนึ่งนาทีไม่ใช่อินฟินิตี้และสามารถลดได้ด้วยวิธีการเชื่อมต่อนี้ () เท่านั้นไม่เพิ่มขึ้น
user207421

หมายเหตุsocket.setSoTimeoutต้องเรียกว่า AFTER ไม่connectเช่นนั้นจะไม่มีผลและการอ่านจะไม่มีวันหมดเวลา นี่คือ gotcha ที่มีเอกสารไม่ดี
pstanton

19

คุณสามารถใช้วิธีแก้ไขปัญหาต่อไปนี้:

SocketAddress sockaddr = new InetSocketAddress(ip, port);
// Create your socket
Socket socket = new Socket();
// Connect with 10 s timeout
socket.connect(sockaddr, 10000);

หวังว่าจะช่วยได้!


1
หากตามที่เขาอ้างว่าเขาได้รับ UnknownHostException มันจะเกิดขึ้นในบรรทัดแรกโดยที่ไม่มีการปรับเปลี่ยนการหมดเวลา
user207421

อย่างไรก็ตามบรรทัดแรกไม่ได้ทำให้เกิดข้อยกเว้นใด ๆ จากเอกสาร: "จะมีการพยายามแก้ไขชื่อโฮสต์ให้เป็น InetAddress หากความพยายามนั้นล้มเหลวที่อยู่จะถูกตั้งค่าสถานะว่ายังไม่ได้รับการแก้ไข"
ady

ซึ่งในกรณีนี้วิธีนี้จะได้รับการแก้ไขconnect()แต่ไม่อยู่ภายใต้การควบคุมของการหมดเวลา
user207421

8

UnknownHostExceptionคุณไม่สามารถควบคุมการหมดเวลาเนื่องจากการ นี่คือการกำหนดเวลา DNS คุณสามารถควบคุมการหมดเวลาการเชื่อมต่อที่กำหนดโฮสต์ที่ถูกต้องเท่านั้น ไม่มีคำตอบก่อนหน้านี้กล่าวถึงประเด็นนี้อย่างถูกต้อง

แต่ฉันพบว่ามันยากที่จะเชื่อว่าคุณได้รับจริงๆUnknownHostExceptionเมื่อคุณระบุที่อยู่ IP แทนที่จะเป็นชื่อโฮสต์

แก้ไขเพื่อควบคุมการหมดเวลา DNS ของ Java ดูคำตอบนี้


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.