Reputation: 13
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
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:
struct
module to pack your string with the required length before itsize_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
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