sending doubles via TCP between Boost ASIO server

2019-08-31 05:59发布

问题:

I am trying to set up a simple Boost ASIO server with a single Java client.

I am able to send and successfully receive strings between the two. However, when I try to send double values, only garbage comes out on the other end.

Below is stand alone code that shows my basic setup (with a C++ Boost ASIO server and a Java client). When they are run, they do the following four sequential tasks:

  1. The client sends a string to the server, which is successfully received and printed out.
  2. The server sends a string to the client, which is successfully received and printed out.
  3. The client sends a double value to the server, which is received but does NOT print out correctly.
  4. The server sends a double value to the client, which is received but does NOT print out correctly.

Does anyone know what I am doing wrong? I am admittedly very new to networking (and Java). I have been through the Boost ASIO documentation and examples but to know avail.

C++ Boost ASIO server code:

#include <iostream>
#include <string>

#include <boost/asio.hpp>
#include <boost/array.hpp>

using boost::asio::ip::tcp;

int main()
{
   unsigned short const PORT = 19876;

   try
   {
      boost::asio::io_service ioService;
      tcp::acceptor acceptor(ioService, tcp::endpoint(tcp::v4(), PORT));

      while (true)
      {
         // Listen for clients
         std::cout << "Listening for client..." << std::endl;
         tcp::socket socket(ioService);
         acceptor.accept(socket);
         std::cout << "Client heard..." << std::endl;

         size_t len;

         // Receive string from client and print it out
         boost::array<char, 128> cBuf;
         len = socket.read_some(boost::asio::buffer(cBuf, sizeof(cBuf)));
         std::cout.write(cBuf.data(), len);

         // Send string to client
         std::string message = "Server string to send to client\n";
         boost::asio::write(socket, boost::asio::buffer(message));

         // Receive double from client and print it out
         double dVal1 = -1.0;
         char * p_dVal1 = reinterpret_cast<char *>(&dVal1);
         len = socket.read_some(boost::asio::buffer(p_dVal1, sizeof(double)));
         std::cout << dVal1<< std::endl; // prints out garbage

         // Send double to client
         double dVal2 = 6.28;
         char const * p_dVal2 = reinterpret_cast<char const *>(&dVal2);
         boost::asio::write(socket, boost::asio::buffer(p_dVal2, sizeof(double)));
      }
   }
   catch (std::exception & e)
   {
      std::cerr << e.what() << std::endl;
   }

   return 0;
}

Java client code:

import java.io.*;
import java.net.*;

public class Client
{
    final static String HOST = "localhost";
    final static int    PORT = 19876;

    public static void main(String[] args) throws IOException
    {
        Socket socket = new Socket(HOST, PORT);

        // Send string to server
        PrintWriter pos = new PrintWriter(socket.getOutputStream(), true);
        pos.println("Client string to send to server");

        // Receive string from server
        BufferedReader bis =
            new BufferedReader(new InputStreamReader(socket.getInputStream()));
        System.out.println(bis.readLine());

        // Send double value to server
        DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
        dos.writeDouble(3.14);

        // Receive double from server
        DataInputStream dis = new DataInputStream(socket.getInputStream());
        System.out.println(dis.readDouble()); // prints out garbage

        socket.close();
        pos.close();
        bis.close();
        dos.close();
        dis.close();
    }
}

Thank you very much in advance!!!

Aaron

回答1:

You need to use a lexical_cast, not a reinterpret_cast.

With reinterpret_cast, you're telling the compiler to literally interpret the double* bit pattern as a const char* bit pattern. Instead, your cast should create a new structure with ascii chars that represent the number in an ascii bit pattern.

Also, you should ensure that you're managing endianess. You should properly convert to and from network endianess on both the client and server. See this answer for additional information.