2008-11-05 16 views
6

पर जावा से सी ++ तक कुशल डेटा स्थानांतरण मैं जावा से सी ++ एप्लिकेशन (एक ही मशीन पर दोनों) से बहुत सारे डेटा (~ 1 गीबिट तक) स्ट्रीम करना चाहता हूं। मैं वर्तमान में लिनक्स पर एक फीफो का उपयोग कर रहा हूं लेकिन विंडोज़ समाधान भी चाहिए। होगा औसत उपयोगकर्ता के नहीं क) मैं गिरी अंतरिक्ष से & को टीसीपी checksumming और नकल से विशाल भूमि के ऊपर नहीं मिलेगा, और ख):विंडोज़

सबसे पार मंच विधि एक स्थानीय सॉकेट प्रतीत हो रहा है, लेकिन फ़ायरवॉल कनेक्शन का निरीक्षण करने की कोशिश कर सकता है और शायद कनेक्शन को अवरुद्ध कर सकता है?

ऐसा लगता है कि जेएनआई और नामित पाइप एपीआई (\। \ पाइप \ blah) का उपयोग करने के लिए एक सुरक्षित समाधान हो सकता है, जिससे कनेक्शन के दोनों किनारों का एक भयानक प्लेटफॉर्म-विशिष्ट गड़बड़ हो।

क्या ये वास्तव में मेरे 2 सबसे अच्छे विकल्प हैं (और लोग कौन सी सिफारिश करेंगे?) धन्यवाद!

उत्तर

4

नामित पाइप टीसीपी की तुलना में अधिक कुशल होंगे, लेकिन साझा स्मृति के बारे में कैसे साझा किया गया ब्लॉक?

मुझे नहीं पता कि साझा की गई स्मृति के साथ इंटरफेसिंग के लिए जावा पक्ष पर कौन सा प्राइमेटिव मौजूद है, लेकिन सी ++ पक्ष से साझा सॉफ़्टवेयर में डेटा को सॉकेट या नामित पाइप से पढ़ने से अधिक कुशल होगा। आपको अपने प्रवाह नियंत्रण को लागू करना होगा और प्राइमेटिव को अवरुद्ध करना होगा, लेकिन ये काफी सीधे हो सकते हैं।

4

मैं स्थानीय सॉकेट का उपयोग करता हूं, जैसा कि आप कहते हैं, सबसे क्रॉस-प्लेटफ़ॉर्म विधि।

कर्नेल-उपयोगकर्ता स्पेस प्रतियां कोई समस्या नहीं होनी चाहिए क्योंकि आप जिस भी अन्य विधि को चुन सकते हैं, उसे साझा की गई स्मृति को छोड़कर इस तरह की प्रतिलिपि की आवश्यकता होगी। यह प्रत्येक यूनिक्स सिस्टम पर उपलब्ध है और विंडोज़ के पास doing it

जावा में साझा मेमोरी का उपयोग करने का एकमात्र तरीका यह है कि इसे अपने आप के माध्यम से कार्यान्वित करना है। डीएलएल/एसओ और जेएनआई इसे एक्सेस करने के लिए।

-2

मैं जेएनआई के खिलाफ सलाह दूंगा, क्योंकि इसे डीबग करना बहुत मुश्किल है। यदि सी ++ कोड segfaults या एक अपवाद अपवाद फेंकता है, तो आपका JVM क्रैश हो जाएगा, और आपको पता नहीं चलेगा क्यों।

+0

यह सच नहीं है। आप जेवीएम को जोड़कर जेएनआई कोड डीबग कर सकते हैं। – JesperE

+0

यदि आप किसी पीसी पर चल रहे हैं तो आप सही हैं। मेरे काम पर, हम एक एम्बेडेड सिस्टम विकसित कर रहे हैं जो लिनक्स चल रहा है, दुर्भाग्यवश, मूल डिबगर नहीं है। जीडीबी भी नहीं। तो जब जेनी कोड दुर्घटनाग्रस्त हो जाता है, तो यह पता लगाना बहुत मुश्किल है कि क्यों। – Dima

0

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

0

System.out और System.in का उपयोग करने के बारे में कैसे?

यदि यह उपयुक्त नहीं है, तो सॉकेट आपकी सबसे अच्छी शर्त है।

7

आपको Google से Protocol Buffers पर एक नज़र डालना चाहिए जो सी ++ और जावा दोनों का समर्थन करता है।

+4

प्रोटोबफ परिभाषित करता है कि आप क्या स्थानांतरित करते हैं, नहीं। सवाल यहाँ कैसे है। – Bruce

+1

प्रोटोबफ के पास अपने डेटा के चारों ओर अपने स्वयं के ओवरहेड हैं, बिना किसी समाधान के कुशलतापूर्वक हस्तांतरण कैसे करें (जैसा कि @ ब्रूस उल्लेख किया गया है)। साझा-स्मृति का प्रयोग करें। – deepmax

0

यदि आपकी सी ++ प्रक्रिया जावा प्रक्रिया शुरू करती है, तो इसे inheritedChannel से लाभ हो सकता है। साथ ही, यदि जावा प्रक्रिया एक फ़ाइल का उपयोग कर रही है, तो मैं transferTo और transferFrom विधियों की खोज की अनुशंसा करता हूं। फ़ाइल IO फ़ाइल करने के लिए फ़ाइल करते समय, ये उपयोगकर्ता और कर्नेल स्पेस के बीच आगे और आगे की ओर जाने से बचते हैं; यदि आप एक विशेष सॉकेट चैनल का उपयोग कर रहे हैं तो वही अनुकूलन ला सकता है।

0

मैं एक यूडीपी "कनेक्शन" की अनुशंसा करता हूं जो गलती के बिना प्राप्त किए गए प्रत्येक एनएच पैकेट को स्वीकार करता है, और कुछ पैकेटों को पुनः प्रेषण का अनुरोध करता है जो इसे याद करेंगे।

1

यदि आप जेएनआई लिखने से खुश हैं, तो Boost.Interprocess पर विचार करें। यह आपको लिनक्स और विंडोज दोनों पर पोर्टेबल साझा मेमोरी देगा। याद रखें कि साझा स्मृति पढ़ने/लिखने के लिए कोई कर्नेल राउंडट्रिप नहीं है।

2

आपका सबसे तेज़ समाधान मेमोरी के साझा खंड को मेमोरी मैपिंग करेगा, और उन्हें एक रिंग-बफर या अन्य संदेश उत्तीर्ण तंत्र को कार्यान्वित किया जाएगा। सी ++ में यह सीधे आगे है, और जावा में आपके पास FileChannel.ma पी विधि है जो इसे संभव बनाता है।

अगला विकल्प दो प्रक्रियाओं के stdin/stdout का उपयोग करना होगा। यदि कोई दूसरा निष्पादित कर सकता है, तो यह काफी तेज़ हो सकता है।

आखिरकार, जैसा कि आपने नोट किया है, आप सॉकेट आईओ कर सकते हैं। वीडियो स्ट्रीमिंग के लिए यह एक अच्छा विकल्प नहीं है, लेकिन यदि आपका गुजरने वाला एक्सएमएल आसपास है, तो अन्य प्रोसेसिंग की तुलना में ओवरहेड न्यूनतम होगा।

1

यदि यह "एक" फ़ंक्शन कॉल में डेटा का एक बड़ा हिस्सा है तो मैं जेएनआई की सिफारिश करता हूं।

इस पर एक नज़र डालें: Sharing output streams through a jni interface

स्निपेट लेख से, यह C++ से जावा के लिए transfert डेटा, विपरीत भी ऐसा करने के लिए आसान होगा:

सभी में, द्विआधारी साझा करने के लिए सामान्य रणनीति जावा के साथ सी से डेटा (ए/वी फाइलें, इमेजेस इत्यादि) बाइट एरे की आवश्यकता है। आप इस तरह सी में एक जावा बाइट सारिणी निर्मित:

const char[] rawData = {0,1,2,3,4,5,6,7,8,9}; //Or get some raw data from somewhere 
int dataSize = sizeof(rawData); 
printf("Building raw data array copy\n"); 
jbyteArray rawDataCopy = env->NewByteArray(dataSize); 
env->SetByteArrayRegion(rawDataCopy, 0, dataSize, rawData); 

और जावा के लिए इसे इस तरह से पारित:

public class MyDataHandler { 
    OutputStream dataStream; 
    public MyDataHandler(OutputStream writeTo) { dataStream = writeTo;} 
    public void handleData(byte[] incomingData) { dataStream.write(incomingData); } 
} 
:

printf("Finding callback method\n"); 
//Assumes obj is the Java instance that will receive the raw data via callback 
jmethodID aMethodId = env->GetMethodID(env->GetObjectClass(obj),"handleData","([B)V"); 
if(0==aMethodId) throw MyRuntimeException("Method not found error"); 
printf("Invoking the callback\n"); 
env->CallVoidMethod(obj,aMethodId, &rawDataCopy); 

आप एक जावा उद्देश्य यह है कि कुछ इस तरह देखा होता

वह हैंडलर मूल विधि के माध्यम से सी को पास किया जाएगा:

public class NativeIntegration { 
    public native void generateBinaryWithHandler(MyDataHandler handler); 

    //Here we assume response is something like a network stream 
    public void doCallNativeFunction(ResponseStream response) { 
    MyDataHandler handler = new MyDataHandler(response); 
    generateBinaryWithHandler(handler); 
    } 
} 

इसके अलावा, आप अन्य तकनीकों का उपयोग कर सकते हैं: कोर्बा, एएसएन .1 (ASN.1 tool), यूडीपी या टीसीपी