Java客户端和C ++服务器通过TCP Socket发送和接收

我有一个C ++服务器和两个客户端(ruby和java)。 一切都在64位Linux机器上运行(java 1.7.0_17)ruby客户端完全正常工作,但java版本存在问题。

在Java中,我尝试从客户端向服务器发送一个String。 实际上,服务器收到了整个字符串,但服务器认为还有更多要接收的内容。

ruby客户端看起来有点像这样:

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

这里的一切都很好。 ruby客户端发送一个字符串。 服务器接收该字符串并发送回复。

Java版本看起来像:

 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(); 

另一方面有一个C ++服务器:

 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; } 

Java消息的服务器输出是:

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

然后没有任何反应。 问题是:

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

陷入了无尽的循环(或类似的东西)。 如果我终止了Java客户端进程或输入了类似的内容:

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

服务器端的输出是:

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

此输出正确(“发送回复成功”除外),但在添加时:

 out.close(); 

客户端无法接收服务器的回复。 因为Socket已关闭。

 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”等不同的分隔符,但服务器仍然认为还有东西要读。 我也尝试使用DatagramSockets:

 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); 

但是服务器无法接受数据包。

ruby-client执行类似socket.shutdownOutput(); (ruby:socket.shutdown 1)调用puts之后。 我改变了java-client-code:

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

它的工作原理!

正如@Charly所说:我必须定义一个“协议”。 在我的情况下,我不允许更改任何与通信相关的代码(在服务器和ruby-client中),因为此function由另一组研究人员使用。 所以我要以这种方式修改我的java-client,它与ruby-client(类似协议) 完全相同

PrintWriter缓冲区(当autoflush为true时)仅通过调用println或printf来刷新。 调用print可能不会刷新缓冲区( Javadoc )。 尝试直接调用println或使用OutputStreamWriter并使用flush()。 注意使用正确的字符集(您可以在OutputStreamWriter构造函数中设置它)。

关闭流分别以这样的方式刷新它:

 DataOutputStream dataOut = new DataOutputStream(socket.getOutputStream()); dataOut.writeUTF(s); dataOut.flush(); 
 while ((recv_count = recv(SocketFD, buffer, sizeof(buffer) - 1, 0)) > 0) { if (recv_count == -1) { 

我不知道你的问题是什么,但这段代码肯定是胡说八道。 内部测试不可能成功。