1

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;
}
3
  • 1
    I don't know how Python works but I doubt it sends the length as a binary integer before it sends the message. Maybe it should be len = ReadBytes(sk, buf, sizeof(buf));? Also I think you may be calculating your buffer wrong in your recv(). Should it be recv(sk, ptr, n - (ptr - buf), 0);? Commented Mar 29, 2015 at 18:34
  • @Galik The C++ code is provided and should not have problems. It cannot be modified otherwise I will prefer to write a python server.anyway thx! Commented Mar 29, 2015 at 18:45
  • Where is the Python equivalent of your C++ ReadBytes function?! It seems you forgot to implement the protocol in Python. Commented Mar 30, 2015 at 9:07

2 Answers 2

1

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)

Sign up to request clarification or add additional context in comments.

3 Comments

Thx for the explanation. I have tried your example, it was close. I got the following info>>received data: o, World!�o��0...... I think I need change the 'i'format to others since it is a 64bit architectures. I have tried 'd' 'q' 'f', they are all failed. I did not find 8bytes long integer format in the python doc. So how can I fix it? Many thx!
It is not working because the C code is not using network byte order. I've edited my answer with a code example that should work for you.
WOW, it works perfectly. Thank you so much. I should learn something about network byte order.
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.