2011-06-15 16 views
5

के गलत संस्करण deserializing मैं सिर्फ जावा पुस्तक से नेटवर्किंग सीख रहा हूँ, तो मैं एक नोब का थोड़ा सा हूँ। मुझे पुस्तक या ऑनलाइन में यह समस्या नहीं मिली, इसलिए मैंने इंटरनेट से पूछने का फैसला किया।(जावा) ऑब्जेक्ट इनपुटपुट ऑब्जेक्ट

पुस्तक ऑब्जेक्टऑटपुटस्ट्रीम और ऑब्जेक्ट इनपुटपुट का उपयोग विभिन्न कंसोल को ऑब्जेक्ट भेजने और प्राप्त करने के लिए कहती है।

अब, मैं सफलतापूर्वक प्राप्त वस्तुओं को प्राप्त करने में सक्षम हूं - लेकिन केवल एक बार। जब मैं अलग-अलग ऑब्जेक्ट भेजता हूं: यादृच्छिक तार और इंटीग्रर्स और नामहीन उदाहरण, कंसोल में सभी सही फ़ील्ड होते हैं। लेकिन जब मैं किसी ऑब्जेक्ट का उदाहरण भेजता हूं, तो उदाहरण के फ़ील्ड में से किसी एक का मान बदलता हूं, और ऑब्जेक्ट को फिर से भेजता है, तो inpustream मूल इंस्टेंस के मान लोड करता है।

तो, उदाहरण के लिए, मेरे पास एक सार्वजनिक int "var" के बराबर कक्षा का एक उदाहरण था। यदि मैं इस वर्ग का उदाहरण भेजता हूं, तो क्लाइंट इसे प्राप्त करता है और सही ढंग से रिपोर्ट करता है कि var = 1. हालांकि , यदि मैं var से 2 (उसी उदाहरण में) बदलता हूं और इसे फिर से भेजता हूं, तो क्लाइंट पढ़ने() विधि को कॉल करना समाप्त कर देगा (इसलिए इसे नई ऑब्जेक्ट प्राप्त होनी चाहिए!), लेकिन यह var के रूप में var की रिपोर्ट करेगा। अगर मैं उदाहरण को एक अलग क्लाइंट को भेजें, जिसने अभी तक इंस्टेंस प्राप्त नहीं किया है, यह सही रूप से 2 के रूप में रिपोर्ट करेगा, और अगर मैं var बदलता हूं तो भी इसे 2 के रूप में रिपोर्ट करना जारी रहेगा।

तथ्य यह है कि क्लाइंट उदाहरण के सही संस्करण को पढ़ता है अगर इसे प्राप्त नहीं किया गया है तो इसका अर्थ यह होना चाहिए कि ऑब्जेक्ट को आउटपुटस्ट्रीम के माध्यम से ठीक से भेजा जा रहा है; किसी कारण से इनपुटस्ट्रीम बस काम नहीं कर रहा है। यह लगभग ऐसा लगता है कि यह वही वस्तु है, इसलिए यह मानता है कि इसकी जांच किए बिना समान मूल्य हैं। ऐसा क्यों होता है और मैं इसे कैसे ठीक कर सकता हूं?

क्षमा करें अगर मैं कुछ बेवकूफ पूछ रहा हूं- पुस्तक यह नहीं बताती है कि धारावाहिकता और सॉकेट कैसे काम करते हैं, बस उनका उपयोग कैसे करें, इसलिए मैं उन्हें मूल रूप से भ्रमित करने के बारे में भ्रमित हो सकता हूं। धन्यवाद!

सरल कोड है कि मैं इस समस्या का परीक्षण करने के लिखा है:

सर्वर:

public void actionPerformed(ActionEvent e) 
{ 
    object.var++; 
      output.write(object); 
      output.flush(); 
      System.out.println(object.var); 
} 

ग्राहक

public void run() 
{ 
    while(true) 
      { 
        Test t = (Test)input.readObject(); 
        System.out.println(t.var); 
      } 
    } 

जब इन प्रोग्राम को चलाने के (एक टाइमर कार्रवाई अद्यतन वस्तुओं भेजने रखने के लिए है) सर्वर वर्ग के लिए आउटपुट 1,2,3,4 है ... असीम रूप से बढ़ रहा है, जबकि ग्राहक का उत्पादन केवल 1,1,1,1,1,1,1, आदि है।

इसे पढ़ने के लिए समय निकालने के लिए धन्यवाद। क्षमा करें अगर मैं सिर्फ गूंगा हूं, तो मैं इस सामान के लिए नया हूं।

संपादित करें: क्षमा करें, पढ़ने() एक गलत टाइप (मैं स्वयं कोड लिखा था क्योंकि मैं स्वरूपण सही Eget नहीं कर सकता है), मैं input.readObject मतलब था()

+0

संबंधित प्रश्न: http://stackoverflow.com/questions/15675262/। –

उत्तर

-1

तो कई घंटे मैंने इस तरह कुछ कोड डीबगिंग बिताया। :)

मुझे यकीन नहीं है कि इसका उचित समाधान क्या है, लेकिन यदि आप ऑब्जेक्ट का नया उदाहरण बनाते हैं, या केवल क्लोन() इसे भेजने से पहले कोड को उम्मीद के अनुसार काम करना चाहिए।

ऐसा लगता है कि वीएम उस ऑब्जेक्ट को पहचानता है जो इसे पहले से प्राप्त कर रहा है, और क्लाइंट में पॉइंटर को वास्तव में अपडेट करने के लिए परेशान किए बिना वास्तव में जांच करता है कि क्या कोई बदलाव है या नहीं।

कोशिश करें ...

public void actionPerformed(ActionEvent e) 
{ 
    object.var++; 
    //assuming your object supports clone() 
    output.write(object.clone()); 
    output.flush(); 
    System.out.println(object.var); 
} 
+1

एक छोटी कार्गो पंथ प्रोग्रामिंग कभी दर्द नहीं करता, आह? –

+0

डेस्क के खिलाफ अपने सिर को मारने के पर्याप्त घंटों के बाद यह पता लगाने की कोशिश कर रहा है कि क्यों सर्वर के सभी क्षेत्रों को प्रिंट करना आपको क्लाइंट की तरफ सभी फ़ील्ड प्रिंट करने से अलग परिणाम देता है, पंथ में शामिल होने से बस एक अच्छा विचार लगता है। ;) – Mike

+4

'ऑब्जेक्टऑटपुटस्ट्रीम.रेसेट' उचित समाधान है :) –

3

आप read() या readObject() ObjectInputStream से उपयोग कर रहे हैं? यदि आप पढ़ रहे हैं() तो आप डेटा का एक बाइट प्राप्त कर रहे हैं। ग्राहक परिवर्तित

public void run() 
{ 
    while(true) 
    { 
    Test t = (Test)input.readObject(); 
    System.out.println(t.var); 
    } 
} 

संपादित करें का प्रयास करें: input.readObject किया गया है चाहिए();

+0

क्या आप कोड को input.readObject() 'में बदलना चाहते हैं? – Bohemian

+0

हां ... मेरी निगरानी देखने के लिए धन्यवाद। मैं संपादित करूँगा। – Suroot

+0

इसके लिए धन्यवाद। पढ़ना() एक int वापस करना इतना भ्रामक है। बर्बाद करने के लिए सभी जावा प्रकार की जांच डालता है। – navjotk

12

कारण यह है कि ObjectOutputStream कैश ऑब्जेक्ट संदर्भों को संदर्भित करता है और यदि समान ऑब्जेक्ट दो बार लिखा जाता है तो स्ट्रीम के पीछे संदर्भ लिखता है। इसका मतलब है कि जब आप write पर कॉल करते हैं, दूसरी बार स्ट्रीम वास्तव में ऑब्जेक्ट की एक नई प्रतिलिपि नहीं लिखती है, तो यह उस ऑब्जेक्ट का संदर्भ डालती है जो पहले से ही लिखी गई है।

आप लिखने के लिए ObjectOutputStream.reset पर कॉल करके इसे रोक सकते हैं। यह स्ट्रीम को किसी भी कैश किए गए संदर्भों को त्यागने के लिए कहता है।

यह व्यवहार अजीब लगता है, लेकिन यह करता है, तो आप एक वस्तु ग्राफ कि वृत्तीय संदर्भ (अर्थात लिखने वस्तु एक बी कि बदले में वापस संदर्भित करता है एक वस्तु पर आपत्ति को संदर्भित करता है कि) है क्रमानुसार करने की कोशिश अनंत लूप को रोकने के लिए वास्तव में आवश्यक है।

+0

यह काम किया! धन्यवाद! – superzipzop

+0

एक उत्तर स्वीकार करने के लिए मत भूलना :) बस अपने पसंदीदा उत्तर के बगल में स्थित चेक मार्क पर क्लिक करें। –

+0

आपने अभी एक समस्या हल की है जिसे मैं घंटों तक काम कर रहा हूं! आपको बहुत - बहुत धन्यवाद! –