简体   繁体   中英

Java client C++ server data send/receive problem

I have created a simple java client, and a c++ server. I am trying to transfer some data from the client to the server. The problem is that when the server receives the data it shows some bad symbols, and also when the server returns some response to the java client, i see those bad symbols again. Could you help me to solve that problem..

java client

 public Client(String host, int port) {
        try {
            String serverHostname = new String(host);

            System.out.println("Connecting to host " + serverHostname + " on port " + port + ".");

            Socket echoSocket = null;
            PrintWriter out = null;
            BufferedReader in = null;

            try {
                echoSocket = new Socket(serverHostname, port);
                out = new PrintWriter(echoSocket.getOutputStream(), true);
                in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
            } catch (UnknownHostException e) {
                System.err.println("Unknown host: " + serverHostname);
                System.exit(1);
            } catch (IOException e) {
                System.err.println("Unable to get streams from server");
                System.exit(1);
            }

            /** {@link UnknownHost} object used to read from console */
            BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));

            while (true) {
                System.out.print("client: ");

                String userInput = stdIn.readLine();
                /** Exit on 'q' char sent */
                if ("q".equals(userInput)) {
                    break;
                }
                out.println(userInput);
                System.out.println("server: " + in.readLine());
            }

            /** Closing all the resources */
            out.close();
            in.close();
            stdIn.close();
            echoSocket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

c++ server

int main()
{
    SOCKET ConSock;
    SOCKET ListenSock;
    SOCKADDR_IN address;
    int addsize = sizeof(address);

    long ok;
    char MESSAGE[200];

    WSAData WSD;
    WORD DllVersion = MAKEWORD(2, 1);

    ok = WSAStartup(DllVersion, &WSD);

    ConSock = socket(AF_INET,SOCK_STREAM,NULL);
    address.sin_addr.s_addr = inet_addr("10.64.15.3");
    address.sin_family = AF_INET;
    address.sin_port = htons(10102);

    ListenSock = socket(AF_INET,SOCK_STREAM,NULL);

    bind(ListenSock,(SOCKADDR*)&address,sizeof(address));
    listen(ListenSock,SOMAXCONN);

    cout<<"Waiting for connection\n";

    while(1)
    {
        if(ConSock = accept(ListenSock,(SOCKADDR*)&address,&addsize))
        {

            ok = recv(ConSock,MESSAGE,sizeof(MESSAGE),NULL);

            string msg;
            msg = MESSAGE;

            cout<<"Client says:\t"<<msg;
            string reply;
            cout<<"\nEnter reply:";
            cin>>reply;

            const char* rep = reply.c_str();

            ok = send(ConSock,rep,1024,NULL);

        }

    }
}

Here is a picture of the input that i am getting from the client: c++ server image

Java character is two bytes. If you encode/decode it on the way out/in it will probably work (given you communicate the string length correctly as well, I have not checked).

StandardCharsets.ISO_8859_1.encode(chars).array() -> byte array
StandardCharsets.ISO_8859_1.decode(bytes).array() -> char array

Next thing that will break as soon as you start sending things other than text or choose to send unicode around and use wstring on the C++ side -- Java is using network byte order, C++ - host byte order (opposite to Java on x86). That's one of reasons.

One last piece of advice - make it work eiter Java-Java or C++-C++ first (whichever language you speak better), then switch to debugging the mix Java-C++.

You just don't length check the buffers anywhere on the C++ side.

in this part

        ok = recv(ConSock,MESSAGE,sizeof(MESSAGE),NULL);

        string msg;
        msg = MESSAGE;

you just assign to msg all of the bytes until it sees a 0 but you never null terminated it, so it just prints the random stuff in memory. This is by the way also a potential buffer overflow.

Something more appropriate might be

        auto byte_count = recv(ConSock,MESSAGE,sizeof(MESSAGE),NULL);

        string msg;
        if(byte_cout > 0 )
        {
            msg.assign(MESSAGE, byte_count);
        }

Something similar is done when you send the whole buffer here:

        cin>>reply;
        const char* rep = reply.c_str();
        ok = send(ConSock,rep,1024,NULL);

You also have a potential buffer overflow by always sending 1024 bytes regardless of how large you buffer was.

Something like this might be better

        cin>>reply;
        ok = send(ConSock,reply.c_str(),reply.size(),NULL);

Edit: full programs with a little more well-defined "end of message" state would be a little like this

Java

public Client(String host, int port) {
    try {
        String serverHostname = new String(host);

        System.out.println("Connecting to host " + serverHostname + " on port " + port + ".");

        Socket echoSocket = null;
        PrintWriter out = null;
        BufferedReader in = null;

        try {
            echoSocket = new Socket(serverHostname, port);
            out = new PrintWriter(echoSocket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
        } catch (UnknownHostException e) {
            System.err.println("Unknown host: " + serverHostname);
            System.exit(1);
        } catch (IOException e) {
            System.err.println("Unable to get streams from server");
            System.exit(1);
        }

        /** {@link UnknownHost} object used to read from console */
        BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));

        while (true) {
            System.out.print("client: ");

            String userInput = stdIn.readLine();
            /** Exit on 'q' char sent */
            if ("q".equals(userInput)) {
                break;
            }
            out.println(userInput);
            //send a newline as a marker for "message is over"
            out.write('\n');
            System.out.println("server: " + in.readLine());
        }

        /** Closing all the resources */
        out.close();
        in.close();
        stdIn.close();
        echoSocket.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

C++ side

int main()
{
    SOCKET ConSock;
    SOCKET ListenSock;
    SOCKADDR_IN address;
    int addsize = sizeof(address);

    long ok;
    char MESSAGE[200];

    WSAData WSD;
    WORD DllVersion = MAKEWORD(2, 1);

    ok = WSAStartup(DllVersion, &WSD);

    ConSock = socket(AF_INET,SOCK_STREAM,NULL);
    address.sin_addr.s_addr = inet_addr("10.64.15.3");
    address.sin_family = AF_INET;
    address.sin_port = htons(10102);

    ListenSock = socket(AF_INET,SOCK_STREAM,NULL);

    bind(ListenSock,(SOCKADDR*)&address,sizeof(address));
    listen(ListenSock,SOMAXCONN);

    cout<<"Waiting for connection\n";

    while(1)
    {
        if(ConSock = accept(ListenSock,(SOCKADDR*)&address,&addsize))
        {
            string msg;
            bool message_finished = false;
            //read into msg until we read a newline at the end or we get an error
            while(!message_finished)
            {
                auto length_read = recv(ConSock,MESSAGE,sizeof(MESSAGE),NULL);
                if(length_read > 0)
                {
                    msg.append(MESSAGE,length_read);
                    message_finished = msg[msg.size()-1] == '\n';
                }
                else if(length_read < 0)
                {
                   //don't continue to just endlessly loop on error
                   message_finished = true;
                }
            }

            cout<<"Client says:\t"<<msg;
            string reply;
            cout<<"\nEnter reply:";
            cin>>reply;
            //append a newline at the end to mark the end of the message
            reply+='\n';
            ok = send(ConSock, reply.c_str(), reply.size(),NULL);

        }

    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM