के माध्यम से भेजता है और प्राप्त करता है मेरे पास एक सी ++ सर्वर और दो क्लाइंट (रूबी और जावा) है। सब कुछ 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();
और यह काम करता है!
जैसा कि @ चार्ली ने कहा: मुझे एक "प्रोटोकॉल" परिभाषित करना है। मेरे मामले में मुझे किसी संचार से संबंधित कोड (सर्वर और रूबी-क्लाइंट में) बदलने की अनुमति नहीं है क्योंकि यह कार्यक्षमता शोधकर्ताओं के किसी अन्य समूह द्वारा उपयोग की जाती है। इसलिए मुझे अपने जावा-क्लाइंट को इस तरह से संशोधित करना है, कि यह सटीकसटीक पर समान चीजें रूबी-क्लाइंट (प्रोटोकॉल की तरह कुछ) के समान ही करता है।
बदल दिया है मैंने पहले से ही pw.flush() का उपयोग किया है लेकिन कुछ भी नहीं बदला गया था। अब मैंने आउटपुटस्ट्रीमवाइटर का उपयोग सीधे करने की कोशिश की: आउट = नया आउटपुटस्ट्रीमवाइटर (सॉकेट.जेटऑटपुटस्ट्रीम(), वर्णसेट .forName ("आईएसओ -885 9 -1")); ... और बाहर। लिखना (संदेश); out.flush(); लेकिन एक ही परिणाम। –
मैंने जावा-क्लाइंट स्रोत –
बदल दिया है, मुझे वास्तव में सी ++ नहीं पता है, लेकिन क्या आपको सर्वर पर संदेश के अंत को इंगित करने के लिए किसी प्रकार का डिलीमीटर नहीं होना चाहिए? जैसा कि मैंने इसे देखा है, कनेक्शन बंद होने पर आपका सर्वर केवल गूंज भेजता है ... उदाहरण के लिए जावा में BufferedReader पर readLine() केवल \ n या \ r पढ़ने पर वापस आ जाएगा। – Charly