2013-04-09 8 views
5

के माध्यम से भेजता है और प्राप्त करता है मेरे पास एक सी ++ सर्वर और दो क्लाइंट (रूबी और जावा) है। सब कुछ 64-बिट लिनक्स-मशीन (जावा 1.7.0_17) पर चल रहा है रूबी क्लाइंट पूरी तरह से काम कर रहा है, लेकिन जावा संस्करण समस्याएं पैदा करता है।जावा क्लाइंट और एक सी ++ सर्वर टीसीपी सॉकेट

जावा में मैंने क्लाइंट से सर्वर पर एक स्ट्रिंग भेजने की कोशिश की। वास्तव में सर्वर को संपूर्ण स्ट्रिंग प्राप्त हुई, लेकिन सर्वर सोचता है कि अभी भी कुछ और प्राप्त करने के लिए है।

माणिक ग्राहक लग रहा है इस तरह एक छोटा सा:

socket = TCPSocket.open(@options[:host],@options[:port]) 
test = "Hello, World" 
socket.puts test 
socket.shutdown 1 
response = socket.gets 

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

जावा संस्करण लगता है:

String ip = "127.0.0.1"; 
int port = 6686; 
java.net.Socket socket = new java.net.Socket(ip,port); 
OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream()); 
InputStreamReader in = new InputStreamReader(socket.getInputStream()); 

String msg = "Hello, world!"; 

//send 
PrintWriter pw = new PrintWriter(out, true); 
pw.print(msg); 
pw.flush(); 
// I also tried: out.write(msg); out.flush(); nothing changed 

//receive the reply 
BufferedReader br = new BufferedReader(in); 
char[] buffer = new char[300]; 
int count = br.read(buffer, 0, 300); 
String reply = new String(buffer, 0, count); 
System.out.println(reply); 

socket.close(); 

दूसरी तरफ है एक सी ++ सर्वर:

string receive(int SocketFD) { 
    char buffer[SOCKET_BUFFER_SIZE]; 
    int recv_count; 

    // empty messagestring 
    string message = ""; 

    // empty buffer 
    memset(buffer, 0, sizeof(buffer)); 

    while ((recv_count = recv(SocketFD, buffer, sizeof(buffer) - 1, 0)) > 0) { 
     /*if (recv_count == -1) { 
     cout << "failed." << endl; 
     break; 
     }*/ 
     cout << recv_count << endl; 
     if (ECHO_SOCKETS) cout << "received: " << buffer << endl; 

     message.append(buffer); 
     memset(buffer, 0, sizeof(buffer)); 

     if (ECHO_SOCKETS) cout << "message is now: " << message << endl; 

    } 
    return message; 
} 

जावा संदेश से सर्वर उत्पादन होता है:

13 
received: Hello, world! 
message is now: Hello, world! 

और फिर कुछ भी नहीं होता है। समस्या यह है कि यह है:

recv(SocketFD, buffer, sizeof(buffer) - 1, 0) 

एक अंतहीन लूप (या ऐसा ही कुछ) में catched है। मैं जावा ग्राहक प्रक्रिया को मारने या मैं की तरह कुछ लिखते हैं, तो:

pw.print(msg); 
out.close(); 

सर्वर साइड पर उत्पादन होता है:

_sending reply: "Request unrecognized/invalid" request="Hello, world!" 
send reply success 
now close connection 

यह आउटपुट सही है ("जबाब सफलता भेजें" को छोड़कर), लेकिन जोड़ने के मामले में:

out.close(); 

क्लाइंट सर्वर का उत्तर प्राप्त नहीं कर सकता है। क्योंकि सॉकेट बंद है।

java.net.SocketException: Socket is closed 
at java.net.Socket.getInputStream(Socket.java:864) 
at MyServer.writeMessage(MyServer.java:56) 
at MyServer.test(MyServer.java:42) 
at MyServer.main(MyServer.java:30) 

संपादित

मैं pw.flush (कॉल करने के लिए) की कोशिश की, और विभिन्न डिलीमीटर जैसे "\ n", "\ r", "\ r \ n" और "\ n \ r" लेकिन सर्वर अभी भी सोचता है कि अभी भी कुछ पढ़ने के लिए है। मैंने डेटाग्राम सॉकेट्स का उपयोग करने की भी कोशिश की:

java.net.DatagramSocket dSocket = new java.net.DatagramSocket(); 
InetAddress address = InetAddress.getByName("localhost"); 
String msg = "Hello, world!"; 
byte[] buf = msg.getBytes(); 
java.net.DatagramPacket packet = new DatagramPacket(buf, buf.length, address, 6686); 

लेकिन सर्वर पैकेट को स्वीकार नहीं कर सकता है।

समाधान

माणिक ग्राहक एक socket.shutdownOutput की तरह कुछ करता है(); (ruby: socket.shutdown 1) डालों के कॉल के बाद। मैंने जावा-क्लाइंट-कोड बदल दिया:

out.write(msg); 
socket.shutdownOutput(); 

और यह काम करता है!

जैसा कि @ चार्ली ने कहा: मुझे एक "प्रोटोकॉल" परिभाषित करना है। मेरे मामले में मुझे किसी संचार से संबंधित कोड (सर्वर और रूबी-क्लाइंट में) बदलने की अनुमति नहीं है क्योंकि यह कार्यक्षमता शोधकर्ताओं के किसी अन्य समूह द्वारा उपयोग की जाती है। इसलिए मुझे अपने जावा-क्लाइंट को इस तरह से संशोधित करना है, कि यह सटीकसटीक पर समान चीजें रूबी-क्लाइंट (प्रोटोकॉल की तरह कुछ) के समान ही करता है।

उत्तर

2

प्रिंटवाइटर बफर (जब ऑटोफ्लश सत्य है) केवल प्रिंटलॉन या प्रिंटफ को कॉल करके फ़्लश किया जाता है। कॉलिंग प्रिंट बफर को फ्लश नहीं कर सकता है (Javadoc)। Println को कॉल करने का प्रयास करें या आउटपुटस्ट्रीमवाइटर का उपयोग सीधे करें और फ्लश करें()। सही वर्णमाला का उपयोग करने के बारे में जागरूक रहें (आप इसे आउटपुटस्ट्रीमवाइटर कन्स्ट्रक्टर में सेट कर सकते हैं)।

+0

बदल दिया है मैंने पहले से ही pw.flush() का उपयोग किया है लेकिन कुछ भी नहीं बदला गया था। अब मैंने आउटपुटस्ट्रीमवाइटर का उपयोग सीधे करने की कोशिश की: आउट = नया आउटपुटस्ट्रीमवाइटर (सॉकेट.जेटऑटपुटस्ट्रीम(), वर्णसेट .forName ("आईएसओ -885 9 -1")); ... और बाहर। लिखना (संदेश); out.flush(); लेकिन एक ही परिणाम। –

+0

मैंने जावा-क्लाइंट स्रोत –

+0

बदल दिया है, मुझे वास्तव में सी ++ नहीं पता है, लेकिन क्या आपको सर्वर पर संदेश के अंत को इंगित करने के लिए किसी प्रकार का डिलीमीटर नहीं होना चाहिए? जैसा कि मैंने इसे देखा है, कनेक्शन बंद होने पर आपका सर्वर केवल गूंज भेजता है ... उदाहरण के लिए जावा में BufferedReader पर readLine() केवल \ n या \ r पढ़ने पर वापस आ जाएगा। – Charly

0

बंद धारा क्रमशः इस तरह एक तरह से यह फ्लश:

DataOutputStream dataOut = new DataOutputStream(socket.getOutputStream()); 
dataOut.writeUTF(s); 
dataOut.flush(); 
+0

हाय मिश, डेटाऑटपुटस्ट्रीम, writeUTF (msg) और फ्लश(); काम नहीं करता recv_count 15 है! सर्वर पर (मैं 13 या 14 स्वीकार करता हूं)। और आउटपुट: cout << "प्राप्त हुआ:" << बफर << endl; खाली है। कोई पात्र नहीं हैं –

0
while ((recv_count = recv(SocketFD, buffer, sizeof(buffer) - 1, 0)) > 0) { 
     if (recv_count == -1) { 

मैं नहीं जानता कि तुम्हारी समस्या क्या है, लेकिन यह निश्चित रूप से कोड बकवास है। कभी भी सफल होने के लिए आंतरिक परीक्षण के लिए असंभव है।

+0

आप सही हैं। यह सिर्फ एक पुराना कोड खंड है। आप इसे अनदेखा कर सकते हैं। –

+0

मैंने सी ++ सर्वर कोड –

संबंधित मुद्दे