আইপি / ও চেষ্টা না করে, কেন টিসিপি সকেটটি পিয়ার দ্বারা কৌতূহলবশত বন্ধ করা হয়েছিল তা সনাক্ত করা কেন অসম্ভব?


93

সাম্প্রতিক একটি প্রশ্নের অনুসরণ হিসাবে , আমি অবাক হয়েছি যে টিসিপি সকেটে পড়ার / লেখার চেষ্টা না করে জাভাতে কেন অসম্ভব, সনাক্ত করতে পারেন যে সকেটটি পিয়ারের দ্বারা নিখুঁতভাবে বন্ধ করা হয়েছে? এটি প্রাক-এনআইও Socketবা এনআইও ব্যবহার করে কিনা তা বিবেচনা না করেই এটি কেস বলে মনে হচ্ছে SocketChannel

যখন কোনও পিয়ার দয়া করে কোনও টিসিপি সংযোগ বন্ধ করে দেয়, সংযোগের উভয় পক্ষের টিসিপি স্ট্যাকগুলি সত্যটি জানে। সার্ভার-সাইড (এক যে শাটডাউন শুরু করে) রাজ্যে শেষ হয় FIN_WAIT2, যেখানে ক্লায়েন্ট-সাইড (যেটি শাটডাউনটিতে স্পষ্টভাবে সাড়া দেয় না) রাজ্যে শেষ হয় CLOSE_WAIT। অন্তর্নিহিত টিসিপি সংযোগটি বন্ধ হয়ে গেছে কিনা তা দেখার জন্য কেন এমন কোনও পদ্ধতি নেই Socketবা SocketChannelযে টিসিপি স্ট্যাকটি জিজ্ঞাসা করতে পারে? এটি কি টিসিপি স্ট্যাকের মতো স্থিতির তথ্য সরবরাহ করে না? বা কার্নেলের মধ্যে ব্যয়বহুল কল এড়াতে এটি কোনও ডিজাইনের সিদ্ধান্ত?

ইতিমধ্যে এই প্রশ্নের কিছু উত্তর পোস্ট করা ব্যবহারকারীদের সহায়তায়, আমি মনে করি যে আমি দেখছি সমস্যাটি কোথা থেকে আসছে। যে পক্ষটি স্পষ্টভাবে সংযোগটি বন্ধ করে দেয় না সেটি টিসিপি অবস্থায় শেষ হয় CLOSE_WAITঅর্থাত্ সংযোগটি বন্ধ করার প্রক্রিয়াধীন এবং পাশের নিজস্ব CLOSEঅপারেশন জারির জন্য অপেক্ষা করে। আমি মনে করি এটি যথেষ্ট ন্যায্য যা isConnectedফিরে আসে trueএবং isClosedফিরে আসে falseতবে কেন এমন কিছু হয় না isClosing?

নীচে পরীক্ষার ক্লাস রয়েছে যা প্রাক-এনআইও সকেট ব্যবহার করে। তবে অভিন্ন ফলাফল এনআইও ব্যবহার করে প্রাপ্ত হয়।

import java.net.ServerSocket;
import java.net.Socket;

public class MyServer {
  public static void main(String[] args) throws Exception {
    final ServerSocket ss = new ServerSocket(12345);
    final Socket cs = ss.accept();
    System.out.println("Accepted connection");
    Thread.sleep(5000);
    cs.close();
    System.out.println("Closed connection");
    ss.close();
    Thread.sleep(100000);
  }
}


import java.net.Socket;

public class MyClient {
  public static void main(String[] args) throws Exception {
    final Socket s = new Socket("localhost", 12345);
    for (int i = 0; i < 10; i++) {
      System.out.println("connected: " + s.isConnected() + 
        ", closed: " + s.isClosed());
      Thread.sleep(1000);
    }
    Thread.sleep(100000);
  }
}

পরীক্ষার ক্লায়েন্ট যখন পরীক্ষার সার্ভারের সাথে সংযোগ করে সার্ভার সংযোগ বন্ধ করার পরেও আউটপুট অপরিবর্তিত থাকে:

connected: true, closed: false
connected: true, closed: false
...

আমি চেষ্টা করেছি আমি উল্লেখ করব: এসসিটিপি প্রোটোকলে এই "সমস্যা" নেই। এসসিটিপিতে টিসিপি হিসাবে অর্ধ-বন্ধ অবস্থায় নেই, অন্য কথায় এক পক্ষ ডেটা প্রেরণ চালিয়ে যেতে পারে না অন্যদিকে প্রান্তটি পাঠানোর সকেট বন্ধ করে দেয়। এটি জিনিস সহজ করা উচিত।
তারনে কলমেন

4
আমাদের দুটি মেলবক্স রয়েছে (সকেট) ........................................... ...... মেলবক্সগুলি রয়্যালমেল (আইপি) ব্যবহার করে প্রত্যেককে মেল প্রেরণ করে টিসিপি সম্পর্কে ভুলে যায় ............................. .................... সব ঠিক আছে এবং জঘন্য, মেলবাক্সগুলি কোনও সমস্যা থেকে উদ্ধার করার সময় প্রত্যেককে (সম্প্রতি ল্যাগের ভার) মেল প্রেরণ / রিসিভ করতে পারে। ............. একটি মেইলবক্স যদি ট্রাকে ধাক্কা খায় এবং ব্যর্থ হয় .... অন্য মেলবক্সটি কীভাবে জানবে? এটি রয়্যাল মেল দ্বারা অবহিত করা উচিত, যিনি পরবর্তীতে এটি জানেন না এবং পরবর্তী সময়ে সেই ব্যর্থ মেইলবক্স থেকে মেল প্রেরণ /
পুনরুদ্ধার করার চেষ্টা করেছিলেন

আপনি যদি সকেট থেকে পড়তে বা সকেটে লিখতে যাচ্ছেন না, তবে আপনার যত্ন কেন? এবং আপনি যদি সকেট থেকে পড়তে চলেছেন বা সকেটে লিখতে চলেছেন তবে কেন অতিরিক্ত চেক করবেন? ব্যবহারের ক্ষেত্রে কী?
ডেভিড শোয়ার্টজ

4
Socket.closeএকটি প্রশংসনীয় ঘনিষ্ঠ হয় না।
ব্যবহারকারী 253751

@ ইমিবিস এটি সর্বাধিক আকর্ষণীয় ঘনিষ্ঠ, যদি না সকেটে অপঠিত ডেটা না থাকে বাফার গ্রহণ করে বা আপনি SO_LINGER এর সাথে গণ্ডগোল না করে।
ব্যবহারকারী 207421

উত্তর:


29

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

আপনি যে কোডটি দিয়েছেন তাতে সকেটটি বন্ধ করা ইনপুট এবং আউটপুট উভয় প্রবাহকে শাটডাউন করে দেবে, যা উপলভ্য হতে পারে এমন ডেটা পড়ার সম্ভাবনা ছাড়াই তাদের ছেড়ে দেওয়া। জাভা Socket.close()পদ্ধতিটি "গ্রেফুল" সংযোগ বিচ্ছিন্ন করে (আমি প্রথমে যা ভেবেছিলাম তার বিপরীতে) কাজ করে যাতে আউটপুট স্ট্রিমের মধ্যে থাকা ডেটা তার কাছাকাছি সিগন্যাল করার জন্য একটি এফআইএন পাঠানো হবে । এফআইএন অন্য পাশ দিয়ে ACK করা হবে, যে কোনও নিয়মিত প্যাকেট 1 হবে

আপনার সকেটটি বন্ধ করার জন্য যদি অন্য পক্ষের জন্য অপেক্ষা করতে হয় তবে আপনাকে তার এফআইএন এর জন্য অপেক্ষা করতে হবে। এবং এটি অর্জন করতে আপনাকে সনাক্ত করতে হবে Socket.getInputStream().read() < 0, যার অর্থ আপনার সকেটটি বন্ধ করা উচিত নয় , কারণ এটি বন্ধInputStream হয়ে যাবে ।

আমি সিতে এবং এখন জাভাতে যা করেছি, সেখান থেকে এ জাতীয় সিনক্রোনাইজড কাছাকাছি অর্জন করা এইভাবে করা উচিত:

  1. শাটডাউন সকেট আউটপুট (অন্য প্রান্তে এফআইএন প্রেরণ করে, এটি সর্বশেষ জিনিস যা এই সকেট দ্বারা প্রেরণ করা হবে)। ইনপুটটি এখনও খোলা রয়েছে যাতে আপনি read()দূরবর্তীটি সনাক্ত করতে পারেনclose()
  2. InputStreamআমরা অন্য প্রান্ত থেকে উত্তর-এফআইএন না পাওয়া পর্যন্ত সকেটটি পড়ুন (এটি এফআইএনটি সনাক্ত করবে, এটি একই কৃপণতাযুক্ত সংযোগ প্রক্রিয়াতে যাবে)। এটি কয়েকটি ওএসের পক্ষে গুরুত্বপূর্ণ কারণ তারা যতক্ষণ না সকেটটি ততক্ষণ বন্ধ করে না যতক্ষণ না এর কোনও বাফারটিতে এখনও ডেটা থাকে। তাদের "ভূত" সকেট বলা হয় এবং ওএসে বর্ণনাকারী সংখ্যাগুলি ব্যবহার করে (এটি আধুনিক ওএসের সাথে আর কোনও সমস্যা হতে পারে না)
  3. সকেটটি বন্ধ করুন (হয় কল করে Socket.close()বা এটি বন্ধ করে InputStreamবা OutputStream)

নিম্নলিখিত জাভা স্নিপেটে প্রদর্শিত হিসাবে:

public void synchronizedClose(Socket sok) {
    InputStream is = sok.getInputStream();
    sok.shutdownOutput(); // Sends the 'FIN' on the network
    while (is.read() > 0) ; // "read()" returns '-1' when the 'FIN' is reached
    sok.close(); // or is.close(); Now we can close the Socket
}

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

@ ওয়ারেনডিউ তাঁর মন্তব্যে যেমন উল্লেখ করেছেন, প্রোগ্রামে (অ্যাপ্লিকেশন স্তর) ডেটা বাতিল করা অ্যাপ্লিকেশন স্তরের একটি অ-প্রশংসনীয় বিচ্ছিন্নতা প্ররোচিত করে: যদিও সমস্ত ডেটা টিসিপি স্তর ( whileলুপ) এ প্রাপ্ত হয়েছিল , সেগুলি বাতিল করা হয়েছে।

1 : " জাভাতে ফান্ডামেন্টাল নেটওয়ার্কিং " থেকে: ডুমুরটি দেখুন। 3.3 পি.45, এবং পুরো §3.7, পিপি 43-48


জাভা একটি চমত্কার ঘনিষ্ঠ সঞ্চালন না। এটা 'পাশবিক' নয়।
ব্যবহারকারী 207421

4
@ ইজেপি, "গ্রেফুল সংযোগ" টিসিপি স্তরে একটি নির্দিষ্ট এক্সচেঞ্জ হচ্ছে, যেখানে ক্লায়েন্টকে সার্ভারের সাথে সংযোগ বিচ্ছিন্ন করার ইচ্ছার ইঙ্গিত দেওয়া উচিত, যা পরিবর্তিতভাবে, পাশটি বন্ধ করার আগে বাকী ডেটা প্রেরণ করে। "অবশিষ্ট ডেটা প্রেরণ করুন" অংশটি প্রোগ্রামটি পরিচালনা করতে হবে (যদিও লোকেরা বেশিরভাগ সময় কিছু না পাঠায়)। কলিংটি socket.close()এইভাবে এই ক্লায়েন্ট / সার্ভার সংকেতকে সম্মান করে না সেভাবে "নির্মম"। কেবলমাত্র তার নিজের সকেট আউটপুট বাফার পূর্ণ হওয়ার পরে সার্ভারকে ক্লায়েন্টের সংযোগ বিচ্ছিন্ন করার বিষয়ে অবহিত করা হবে (কারণ কোনও পক্ষের পক্ষ থেকে কোনও ডেটা অ্যাকড করা হচ্ছে না, যা বন্ধ ছিল)।
ম্যাথিউউ

আরও তথ্যের জন্য এমএসডিএন দেখুন ।
ম্যাথিউউ

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

4
@ লিওনিডউসভ এটি সহজভাবে ভুল। জাভা read()স্ট্রিমের শেষে -1 ফিরে আসে এবং আপনি যতবার কল করেছেন ততক্ষণ তা চালিয়ে যেতে পারেন। এসি read()বা recv()স্ট্রিমের শেষে শূন্য ফিরে আসে এবং আপনি যতবার কল করেছেন ততক্ষণ এটি চালিয়ে যেতে থাকে।
ব্যবহারকারী 207421

18

আমি মনে করি এটি সকেট প্রোগ্রামিং প্রশ্ন বেশি। জাভা সকেট প্রোগ্রামিং traditionতিহ্যটি অনুসরণ করছে।

উইকিপিডিয়া থেকে :

টিসিপি একটি কম্পিউটারের একটি প্রোগ্রাম থেকে অন্য কম্পিউটারে অন্য কম্পিউটারে বাইটের একটি স্ট্রিমের নির্ভরযোগ্য, অর্ডার দেওয়া হয়।

একবার হ্যান্ডশেক হয়ে গেলে, টিসিপি দুটি শেষ পয়েন্ট (ক্লায়েন্ট এবং সার্ভার) এর মধ্যে কোনও পার্থক্য করে না। "ক্লায়েন্ট" এবং "সার্ভার" শব্দটি বেশিরভাগ সুবিধার জন্য। সুতরাং, "সার্ভার" ডেটা প্রেরণ করতে পারে এবং "ক্লায়েন্ট" একে অপরের কাছে একই সাথে অন্য কিছু ডেটা প্রেরণ করতে পারে।

"ক্লোজ" শব্দটিও বিভ্রান্তিকর। কেবলমাত্র এফআইএন ঘোষণা আছে, যার অর্থ "আমি আপনাকে আর কোনও জিনিস প্রেরণ করব না।" তবে এর অর্থ এই নয় যে ফ্লাইটে কোনও প্যাকেট নেই, বা অন্যটির আর কিছু বলার নেই। যদি আপনি শামুক মেইলটিকে ডেটা লিঙ্ক স্তর হিসাবে প্রয়োগ করেন বা আপনার প্যাকেটটি বিভিন্ন রুট ভ্রমণ করেছে তবে এটি সম্ভব যে প্রাপক ভুল ক্রমে প্যাকেটগুলি গ্রহণ করে। আপনার জন্য কীভাবে এটি ঠিক করতে হবে তা টিসিপি জানে।

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


4
আমি মনে করি না, আপনি উভয় উইন্ডো এবং লিনাক্সে সি কোডে রাজ্যের জন্য পরীক্ষা করতে পারেন !!! কিছু কারণে জাভা কিছু জিনিস প্রকাশ করতে পারে না, যেমন উইন্ডোজ এবং লিনাক্সে থাকা গেসকোপ্ট ফাংশনগুলি প্রকাশ করা ভাল। আসলে, নীচের উত্তরগুলিতে লিনাক্স পাশের জন্য কিছু লিনাক্স সি কোড রয়েছে।
ডিন হিলার

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

4
এটা তোলে করেন গড় 'সেখানে ফ্লাইট আর কোনো প্যাকেট হল'। এফআইএন ফ্লাইটে কোনও ডেটার পরে প্রাপ্ত হয় । তবে এর অর্থ এই নয় যে পিয়ার ইনপুটটির জন্য সকেটটি বন্ধ করে দিয়েছে আপনাকে ** কিছু প্রেরণ করতে হবে * এবং এটি সনাক্ত করতে একটি 'সংযোগ পুনরায় সেট' করতে হবে। FIN বলতে কেবল আউটপুটটির জন্য একটি শাটডাউন বোঝাতে পারত।
ব্যবহারকারী 207421

11

অন্তর্নিহিত সকেট এপিআই-তে এই জাতীয় বিজ্ঞপ্তি নেই।

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


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

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

4
যা ঘটে তা হ'ল সংযোগের পক্ষগুলি <code> CLOSE_WAIT </code> এবং <code> FIN_WAIT_2 </code> এ শেষ হয় এবং এটি এই অবস্থায় <code> isConceected () </code> এবং <কোড> isClosed () </code> এখনও দেখতে পাচ্ছেন না যে সংযোগটি বন্ধ হয়ে গেছে।
আলেকজান্ডার

আপনার পরামর্শের জন্য ধন্যবাদ! আমি মনে করি আমি এখন বিষয়টি আরও ভাল করে বুঝতে পারি। আমি প্রশ্নটি আরও নির্দিষ্ট করে দিয়েছি (তৃতীয় অনুচ্ছেদ দেখুন): কেন অর্ধ-বন্ধ সংযোগগুলির জন্য পরীক্ষা করার জন্য "সকেট.আইসক্লোজিং" নেই?
আলেকজান্ডার

8

যেহেতু এখনও পর্যন্ত কোনও উত্তরই পুরোপুরি প্রশ্নের উত্তর দেয় না, তাই আমি আমার বর্তমান বোঝার সংক্ষিপ্তসার করছি।

যখন কোনও টিসিপি সংযোগ স্থাপন করা হয় এবং একটি পিয়ার কল করে close()বা shutdownOutput()তার সকেটে, সংযোগের অপর পাশে সকেটটি CLOSE_WAITরাজ্যে রূপান্তর করে । নীতিগতভাবে, কোনও সকেট CLOSE_WAITকল না করেই অবস্থিত কিনা তা টিসিপি স্ট্যাকের মাধ্যমে খুঁজে পাওয়া সম্ভব read/recv(যেমন, getsockopt()লিনাক্সে: http://www.developerweb.net/forum/showthread.php?t=4395 ), তবে তা নয় সুবহ.

জাভার Socketক্লাসটি একটি বিএসডি টিসিপি সকেটের সাথে তুলনাযোগ্য একটি বিমূর্ততা সরবরাহ করার জন্য ডিজাইন করা হয়েছে বলে মনে হয়, সম্ভবত এটি কারণ যে টিসিপি / আইপি অ্যাপ্লিকেশনগুলি প্রোগ্রামিং করার সময় লোকেদের ব্যবহার করা হত st বিএসডি সকেটগুলি কেবল একটি আইএনইটি (উদাহরণস্বরূপ, টিসিপি) ব্যতীত অন্য একটি সমর্থনকারী সকেটকে সমর্থন করে, সুতরাং তারা কোনও সকেটের টিসিপি অবস্থা সন্ধানের কোনও বহনযোগ্য উপায় সরবরাহ করে না।

isCloseWait()বিএসডি সকেটগুলির দ্বারা প্রদত্ত বিমূর্ততার স্তরে লোকেরা টিসিপি অ্যাপ্লিকেশনগুলি প্রোগ্রামিং করতে অভ্যস্ত বলে কোনও পদ্ধতি নেই কারণ জাভা কোনও অতিরিক্ত পদ্ধতি সরবরাহের প্রত্যাশা করে না।


4
বা জাভা বহনযোগ্যভাবে কোনও অতিরিক্ত পদ্ধতি সরবরাহ করতে পারে না । হতে পারে তারা একটি ক্লোসওয়েট () পদ্ধতি তৈরি করতে পারে যা প্ল্যাটফর্মটি সমর্থন না করলে মিথ্যা ফিরে আসবে, তবে কেবলমাত্র সমর্থিত প্ল্যাটফর্মগুলিতে পরীক্ষা করা হলে কতজন প্রোগ্রামার সেই গোটচায় কামড়িত হবে?
প্রচারিত

4
এটা দেখে মনে হচ্ছে আমার কাছে পোর্টেবল হতে পারে ... জানালা এই আছে msdn.microsoft.com/en-us/library/windows/desktop/... এবং এই Linux pubs.opengroup.org/onlinepubs/009695399/functions/...
ডিন Hiller

4
এটি এমন নয় যে প্রোগ্রামাররা এটিতে অভ্যস্ত; এটি সকেট ইন্টারফেস যা প্রোগ্রামারদের জন্য দরকারী। মনে রাখবেন যে সকেট বিমূর্তি টিসিপি প্রোটোকলের চেয়ে বেশি ব্যবহৃত হয়।
ওয়ারেন শিশ

জাভাতে এমন কোনও পদ্ধতি নেই isCloseWait()কারণ এটি সমস্ত প্ল্যাটফর্মগুলিতে সমর্থিত নয়।
ব্যবহারকারী 207421

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

7

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

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

যদি আপনি প্রকৃতপক্ষে আপনার প্রোটোকলে ওওবি ডেটা ব্যবহার করেন তবে আপনার মাইলেজটি আলাদা হতে পারে।


4

যখন জাভা আইও স্ট্যাকটি হঠাৎ টিয়ারডাউনতে ধ্বংস হয়ে যায় তখন অবশ্যই এফআইএন প্রেরণ করে। এটি কেবল কোনও ধারণা দেয় না যে আপনি এটি সনাক্ত করতে পারবেন না, খ / সি বেশিরভাগ ক্লায়েন্ট কেবল সংযোগ বন্ধ করে দিলে কেবল এফআইএন পাঠায়।

... অন্য কারণে আমি সত্যিই এনআইও জাভা ক্লাসকে ঘৃণা করতে শুরু করি। মনে হচ্ছে সবকিছু কিছুটা অর্ধ-গাধা।


4
এছাড়াও, এটি উপস্থিত হয় যখন আমি কোনও এফআইএন উপস্থিত থাকি তখন আমি কেবল পঠিত স্ট্রিমের সমাপ্তি পাই (-1 রিটার্ন)। সুতরাং আমি পঠনের পার্শ্বে একটি শাটডাউন সনাক্ত করতে এটিই একমাত্র উপায়।

4
আপনি এটি সনাক্ত করতে পারেন। আপনি পড়ার সময় EOS পান। এবং জাভা এফআইএন পাঠায় না। টিসিপি তা করে। জাভা টিসিপি / আইপি প্রয়োগ করে না, এটি কেবল প্ল্যাটফর্ম বাস্তবায়ন ব্যবহার করে।
ব্যবহারকারী 207421

4

এটি একটি আকর্ষণীয় বিষয়। আমি এখনই জাভা কোডটি খনন করেছি যাচাই করতে। আমার সন্ধান থেকে, দুটি স্বতন্ত্র সমস্যা রয়েছে: প্রথমটি টিসিপি আরএফসি নিজেই, যা দূর থেকে বন্ধ সকেটকে অর্ধ-দ্বৈততে ডেটা প্রেরণ করতে দেয়, তাই একটি দূরবর্তীভাবে বন্ধ সকেটটি এখনও অর্ধেক উন্মুক্ত। আরএফসি অনুসারে, আরএসটি সংযোগটি বন্ধ করে না, আপনাকে একটি স্পষ্টত ABORT কমান্ড প্রেরণ করতে হবে; সুতরাং জাভা অর্ধেক বন্ধ সকেটের মাধ্যমে ডেটা প্রেরণের অনুমতি দেয়

(শেষ প্রান্তের উভয় ক্ষেত্রেই নিকটস্থ অবস্থান পড়ার দুটি পদ্ধতি রয়েছে are)

অন্য সমস্যাটি হ'ল বাস্তবায়ন বলে যে এই আচরণটি optionচ্ছিক। জাভা যেমন পোর্টেবল হওয়ার চেষ্টা করে, তারা সেরা সাধারণ বৈশিষ্ট্যটি প্রয়োগ করে। আমার ধারণা, (ওএস, অর্ধ দ্বৈত প্রয়োগ) একটি মানচিত্র বজায় রাখা একটি সমস্যা হত।


4
আমি মনে করি আপনি আরএফসি 793 ( faqs.org/rfcs/rfc793.html ) বিভাগের সাথে সংযোগ বন্ধ করে দিচ্ছেন 3.5.৩ আমি নিশ্চিত নই যে এটি সমস্যার সমাধান করেছে, কারণ উভয় পক্ষই সংযোগের চমত্কার শাটডাউনটি সম্পূর্ণ করে এবং এমন রাজ্যে শেষ হয় যেখানে তাদের কোনও ডেটা প্রেরণ / গ্রহণ করা উচিত নয়।
আলেকজান্ডার

নির্ভর করে। সকেটে আপনি কতটি এফআইএন দেখতে পাচ্ছেন? এছাড়াও, প্ল্যাটফর্ম নির্দিষ্ট সমস্যা হতে পারে: সম্ভবত উইন্ডোজ প্রতিটি এফআইএনকে একটি এফআইএন দিয়ে উত্তর দেয় এবং সংযোগ দুটি প্রান্তে বন্ধ হয়ে যায়, তবে অন্যান্য অপারেটিং সিস্টেমগুলি এইভাবে আচরণ করতে পারে না এবং এই সমস্যাটি দেখা দেয় যেখানে 2 সমস্যা দেখা দেয় maybe
এইখানেই

4
না, দুর্ভাগ্যক্রমে এমনটি হয় না। এই আউটপুটশুটডাউন এবং আইপুটশুটডাউনটি এই "আবিষ্কার" এর মুখোমুখি হওয়ার সময় সবার আগে চেষ্টা করে তবে উভয় পদ্ধতিই মিথ্যা ফিরে আসে। আমি এটি এখন উইন্ডোজ এক্সপি এবং লিনাক্স 2.6 এ পরীক্ষা করেছি tested সমস্ত 4 পদ্ধতির রিটার্ন মানগুলি পড়ার চেষ্টা করার পরেও একই থাকে
আলেকজান্ডার

4
রেকর্ডের জন্য, এটি অর্ধ-দ্বৈত নয়। অর্ধ-দ্বৈত অর্থ শুধুমাত্র এক পক্ষ এস সময়ে প্রেরণ করতে পারে; উভয় পক্ষ এখনও প্রেরণ করতে পারেন।
rbp

4
এই ইনপুটশুটডাউন এবং আইসপুটশুটডাউনটি সংযোগটির স্থানীয় প্রান্তটি পরীক্ষা করে - আপনি এই সকেটে শাটডাউন ইনপুট বা শাটডাউন আউটপুট বলেছিলেন কিনা তা জানতে এটি পরীক্ষা করা হয়। তারা আপনাকে সংযোগের দূরবর্তী প্রান্ত সম্পর্কে কিছুই বলবে না।
মাইক ডিমিক

3

এটি জাভা এর (এবং অন্য সকলের 'আমি দেখেছি) ওও সকেট শ্রেণীর একটি ত্রুটি - নির্বাচিত সিস্টেম কলটিতে অ্যাক্সেস নেই।

সি তে সঠিক উত্তর:

struct timeval tp;  
fd_set in;  
fd_set out;  
fd_set err;  

FD_ZERO (in);  
FD_ZERO (out);  
FD_ZERO (err);  

FD_SET(socket_handle, err);  

tp.tv_sec = 0; /* or however long you want to wait */  
tp.tv_usec = 0;  
select(socket_handle + 1, in, out, err, &tp);  

if (FD_ISSET(socket_handle, err) {  
   /* handle closed socket */  
}  

আপনি একই জিনিস করতে পারেন getsocketop(... SOL_SOCKET, SO_ERROR, ...)
ডেভিড শোয়ার্জ

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

4
আপনি 'সিলেক্টর' ক্লাস ব্যবহার করতে পারেন 'সিলেক্ট ()' সিস্কেল অ্যাক্সেস করতে। এটি যদিও এনআইও ব্যবহার করে।
ম্যাথিউউ

4
অপর পক্ষের বন্ধ হয়ে যাওয়া সংযোগ সম্পর্কে ব্যতিক্রমী কিছুই নেই।
ডেভিড শোয়ার্টজ

4
অনেক প্লাটফর্ম, সহ জাভা, না নির্বাচন () সিস্টেম কল অ্যাক্সেস প্রদান করে।
ব্যবহারকারী 207421

2

এখানে একটি খোঁড়া কাজ। এসএসএল ব্যবহার করুন;) এবং এসএসএল টিয়ারডাউনটিতে একটি ঘনিষ্ঠ হ্যান্ডশেক করে যাতে আপনাকে সকেটটি বন্ধ হয়ে যাওয়ার বিষয়ে অবহিত করা হয় (বেশিরভাগ বাস্তবায়ন মনে হয় যে এটি হ্যান্ডশেক টিয়ারডাউন যা হ'ল)।


4
জাভাতে এসএসএল ব্যবহার করার সময় কেউ কীভাবে সকেটটি বন্ধ করে দেওয়া হবে?
ডেভ বি

2

এই আচরণের কারণ (যা জাভা নির্দিষ্ট নয়) এটি হ'ল আপনি টিসিপি স্ট্যাক থেকে কোনও স্থিতির তথ্য পান না। সর্বোপরি, একটি সকেট হ'ল অন্য একটি ফাইল হ্যান্ডেল এবং এটি আবিষ্কার করার জন্য প্রকৃত ডেটা আছে কিনা তা আপনি জানতে পারবেন না ( select(2)সেখানে সাহায্য করবে না, এটি কেবলমাত্র এটি আপনাকে ইঙ্গিত দেয় যে আপনি চেষ্টা করতে পারেন)।

আরও তথ্যের জন্য ইউনিক্স সকেট এফএকিউ দেখুন


4
রিয়ালবাসিক সকেটগুলি (ম্যাক ওএস এক্স এবং লিনাক্সে) বিএসডি সকেটের উপর ভিত্তি করে, তবুও আরবি আপনাকে একটি দুর্দান্ত ত্রুটি দিতে পরিচালিত করে 102 অন্য সংযোগটি যখন প্রান্তটি বাদ যায় তখন dropped সুতরাং আমি মূল পোস্টারটির সাথে একমত, এটি সম্ভব হওয়া উচিত এবং জাভা (এবং কোকো) এটি সরবরাহ না করে এমন লম্পট।
জো স্ট্রাউট

4
আপনি জো আইআউটআউট কেবল তখনই করতে পারেন যখন আপনি কিছু আই / ও করেন। এমন কোনও এপিআই নেই যা আপনাকে আই / ও না করে সংযোগের স্থিতি দেবে। পিরিয়ড। এটি জাভার ঘাটতি নয়। এটি টিসিপিতে 'ডায়াল টোন' না থাকার কারণে এটি ইচ্ছাকৃতভাবে নকশার বৈশিষ্ট্য।
ব্যবহারকারী 207421

select() ডেটা বা ইওএস আছে কিনা তা অবরুদ্ধ না করে পড়ার জন্য আপনাকে জানায়। 'আপনি বাধা না দিয়ে চেষ্টা করতে পারেন এমন সিগন্যাল' অর্থহীন। আপনি যদি অবরুদ্ধকরণ মোডে থাকেন তবে আপনি সর্বদা ব্লক না করে চেষ্টা করতে পারেন । select()সকেটের ডেটা দ্বারা চালিত বাফার গ্রহণ করে বা সকেটে প্রেরিত বাফার বা এফআইএন বা সকেটে স্পেস পাঠান।
ব্যবহারকারী 207421

@ এজেপি কি হবে getsockopt(SO_ERROR)? প্রকৃতপক্ষে, এমনকি getpeernameসকেটটি এখনও সংযুক্ত থাকলেও আপনাকে জানাবে।
ডেভিড শোয়ার্জ

0

কেবল লেখালেখির জন্য প্রয়োজন যে প্যাকেটগুলি বিনিময় করা হবে যা সংযোগের ক্ষতি নির্ধারণ করার অনুমতি দেয়। প্রায় একটি সাধারণ কাজ হ'ল কেপ ALIVE বিকল্পটি ব্যবহার করা।


আমি মনে করি যে কোনও এন্ডপয়েন্টটি কোনও পেওলড না লিখে এফআইএন সেট সহ একটি প্যাকেট পাঠিয়ে একটি ক্রেফুল সংযোগ শাটডাউন শুরু করার অনুমতি দেওয়া হয়েছে।
আলেকজান্ডার

@ আলেকজান্ডার অবশ্যই এটি করে তবে এটি এই উত্তরটির সাথে প্রাসঙ্গিক নয়, যা সংযোগের কম সনাক্তকরণের বিষয়ে ।
ব্যবহারকারী 207421

-3

যখন অর্ধ-খোলা জাভা সকেটগুলির সাথে ডিল করার বিষয়টি আসে, তখন কেউ আইসপুটশুটডাউন () এবং আউটপুটশুটডাউন () দেখতে পারেন


না, এটি আপনাকে কেবল কী বলেছিল তা জানায় না, পীর যা বলেছিলেন তা নয়।
ব্যবহারকারী 207421

এই বিবৃতিটির জন্য আপনার উত্স ভাগ করে নেওয়ার যত্ন?
জিমিবি

4
বিপরীতে আপনার উত্স ভাগ করে যত্ন? এটা আপনার বক্তব্য। আপনার কাছে যদি প্রমাণ থাকে তবে চলুন। আমি দৃ as়ভাবে বলছি যে আপনি ভুল বলেছেন। পরীক্ষাটি করুন এবং আমাকে ভুল প্রমাণ করুন।
ব্যবহারকারী 207421

তিন বছর পরে এবং কোন পরীক্ষা। Qed
user207421
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.