user3753445
user3753445

Reputation: 13

C++ server cannot read my message from python client via socket

I have wrote a python client script to send message to the server via tcp.

import socket

TCP_IP = '127.0.0.1'
TCP_PORT = 12003
BUFFER_SIZE = 1024
MESSAGE = b"Hello, World!"

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(MESSAGE)
data = s.recv(BUFFER_SIZE)
s.close()

print "received data:", data

The server can receive my data, but it seems it cannot read the data. The log info is copied in following.

I0328 21:45:24.493249   505 prset04.cpp:210] reading the message (3472609771221168177 bytes)
E0328 21:45:25.493088   505 prset04.cpp:162] unable to receive on socket
I0328 21:45:25.493285   505 prset04.cpp:215] echoing the message
E0328 21:45:25.493479   505 prset04.cpp:185] unable to send on socket

What I think is there may be something different between C++ socket module and python's. But I don't know what goes wrong there since I am not familiar with C++ and socket.

Any ideas or explanation will be greatly helpful!

Thanks

server code:

static void OnClient(const int sk) {
    size_t len;
    char buf[1024];

    // Read the message length.
    if (!ReadBytes(sk, reinterpret_cast<char*>(&len), sizeof(len))) {
        LOG(ERROR) << "unable to read message length";
        return;
    }

    LOG(INFO) << "reading the message (" << len << " bytes" << ")";

    // Read the message.
    ReadBytes(sk, buf, len);

    LOG(INFO) << "echoing the message";

    // Echo the message.
    WriteBytes(sk, buf, len);
}

static bool ReadBytes(const int sk, char* buf, const size_t n) {
    char* ptr = buf;
    while (ptr < buf + n) {
        if (!SetReadTimeout(sk)) {
            return false;
        }

        auto ret = recv(sk, ptr, ptr - buf + n, 0);
        if (ret <= 0) {
            LOG(ERROR) << "unable to receive on socket";
            return false;
        }

        ptr += ret;
    }

    return true;
}

Upvotes: 1

Views: 1168

Answers (2)

Christian Eichelmann
Christian Eichelmann

Reputation: 968

Like Galik already said, Python doesn't send the length of the string before the string, like your programm expects it. And C/C++ doesn't do this either.

If you want your Python program to work with your C programm, there are several things you have to consider:

  1. Use the struct module to pack your string with the required length before it
  2. Use the network byte order when packing your string
  3. You should be aware that declarations like size_t are architecture dependant and vary between 64 and 32 bit architectures. You can use fixed size integers like uint32_t if you want them to be compatible between architectures.

Example Code:

from struct import pack
message = "Hello World"
data = pack('!i%ds' % len(message), len(message), message))

If you can't change the C-Code to use the network byte order, your specific code should look like this:

from struct import pack
message = "Hello World"
data = pack('<Q%ds' % len(message), len(message), message))

< = Use little endian byte order

Q = Use an unsigned 64 bit integer (sizet_t on 64Bit architectures)

Upvotes: 1

Bogolt
Bogolt

Reputation: 520

As Galik pointed out your python script does not send any length of the message. While your c++ server reads 4 bytes ( 8 if you are on 64 bit linux ) and expect them to be length of the message. So first 4 bytes are "Hell" which binary form will be quite a big number of bytes your server tries to read.

To fix this - send first 4 bytes as message length in your python script. Also you'll need to use network byte order ( if you plan to stuck with binary ) to make sure bytes read properly. Use ntohl() function to convert from network to host byte order number.

Upvotes: 0

Related Questions