Java客户端和C ++服务器通过TCP Socket发送和接收 [英] Java client and a C++ server send and receive via TCP Socket

查看:145
本文介绍了Java客户端和C ++服务器通过TCP Socket发送和接收的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个C ++服务器和两个客户端(ruby和java)。
一切都运行在一个64位的linux机器(java 1.7.0_17)
ruby​​客户端是完全工作,但是java版本出现问题。

I have a C++ server and two clients (ruby and java). Everything is running on a 64-bit linux-machine (java 1.7.0_17) The ruby client is fully working, but the java version makes problems.

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

In Java I tried to send a String from the client to the server. Actually the Server received the entire String, but the server thinks there is still something more to receive.

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

The ruby client looks a little bit like this:

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


$ b b

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

Everything here is working fine. The ruby client sends a string. The server receives that string and sends a reply.

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 ++服务器:

On the other side there is a C++ Server:

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消息的服务器输出为:

The server output from the Java-message is:

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


问题是:

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

无限循环(或类似的东西)。
如果我杀死Java客户端进程或者我键入类似:

is catched in an endless loop (or something like that). If I kill the Java-client process or I type something like:

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

服务器端的输出是:

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

这个输出是正确的发送回复成功),但如果添加:

This output is right (except "send reply success"), but in case of adding:

out.close();

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

the client can't receive the reply of the server. Because the Socket is closed.

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\\\
和\\\
\r,但服务器仍然认为还有东西要读。我也尝试使用DatagramSockets:

Edit

I tried to call pw.flush(); and different delimiters like "\n", "\r", "\r\n" and "\n\r" but the server still thinks there is still something to read. I also tried to use 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);

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

But the server can't accept the packet.

ruby​​-client会执行类似socket.shutdownOutput (ruby:socket.shutdown 1)。我改变了java-client-code:

The ruby-client does something like a socket.shutdownOutput(); (ruby: socket.shutdown 1) after the call of puts. I changed the java-client-code:

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

并且有效!

Charly说:我必须定义一个协议。在我的情况下,我不允许改变任何通信相关的代码(在服务器和ruby客户端),因为这个功能是由另一组研究人员使用。因此,我必须以这种方式修改我的java客户端,它在 exact 同样的时间执行与ruby-client相同的 exact )。

As @Charly said: I have to define a "protocol". In my case I'm not allowed to change any communication related code (in the server and the ruby-client) because this functionality is used by a another group of researchers. So I've to modify my java-client in that way, that it does the exact same things at the exact same time as the ruby-client (something like a protocol).

推荐答案

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

PrintWriter buffer (when autoflush is true) is only flushed by calling println or printf. Calling print may not flush the buffer (Javadoc). Try calling println or use a OutputStreamWriter directly and flush(). Be aware of using the right charset (You can set it up in OutputStreamWriter constructor).

这篇关于Java客户端和C ++服务器通过TCP Socket发送和接收的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆