0

正在更新我的应用程序,该应用程序使用套接字从 python 到 C 程序进行通信,以便在发送消息时使用固定长度的标头作为协议。

作为我的 C 客户端代码的测试示例:

/*
Socket definition code put inside here
*/


char test2[] = "hello this is a test";

uint32_t test = sizeof(test2); //Get size of message and store in 32bit int
uint32_t test_conv = htonl(test); //Convert to network byte order

header = send(ConnectSocket, &test_conv, sizeof(uint32_t), 0); //Send size of message

body = send(ConnectSocket, test2, sizeof(test2), 0); //Send the actual message

这是python服务器代码的摘录:

msg = clientsocket.recv(4)

msg_length = int.from_bytes(msg, sys.byteorder) //Get the header with the message length 
msg_length = socket.ntohl(msg_length)
if len(msg) > 0:
    print(f"This message length: {test} ")

msg = clientsocket.recv(msg_length) //Get the message

if len(msg)>0:
    print(f'Message is: {msg.decode("utf-8")}')

服务器.py 输出:

The message length: 21
Message is: hello this is a test

我在这篇文章中省略了套接字头和其他内容以及错误检查以节省空间。

这是使用固定长度标头的安全方法吗?我并不期待大量的流量,我只会在每条消息中发送一两句话的信息。

我的最后一个问题是为什么在 C 中调用 send 时我使用 '&test_conv' 作为消息参数。这不仅仅是发送 test_conv 变量的地址值。我不需要发送实际消息,而不是地址吗?

感谢您提供任何见解,如果我应该使用不同的实现,请提供任何资源链接。

4

2 回答 2

1

您的解决方案依赖于一个固定大小的整数来宣布以下消息中的字节数,这对我来说似乎是正确的。
请确保在您的实际程序中始终使用sizeof和/或strlen()用于文本消息。
在您的示例中,传输sizeof(text2)字节包括;'\0'末尾的隐式。text2然后在接收时构建的 python 字符串包含这个无用的(不可见但仍然存在)空字节作为最后一个字符。

关于&test_convin send(),您需要了解此系统调用仅考虑字节序列。
它不知道这些字节包含在一个整数中。
这就是为什么您提供要发送的第一个字节的地址 ( &test_conv) 和sizeof(uint32_t)从该地址开始要发送的字节数 ( )。
接收器将获得完全相同的字节序列,并将它们解释为 32 位整数的内存表示(当然要考虑字节序)。

请注意,structpython 中的包可以帮助处理整数和字节序的内存表示。

于 2020-03-26T22:40:57.133 回答
0

在我看来,您应该使用网络字节顺序,而不是主机字节顺序。

另外,我相信 send() 和 recv() 可以提前返回,而无需传输所有请求的内容 - 这就是它们返回长度的原因。通常他们会传输你的所有数据并返回完整的长度,但他们不能保证这样做。

对于 python,我喜欢我的http://stromberg.dnsalias.org/~dstromberg/bufsock.html模块。它会为您处理恢复。

对于 C,我认为人们几乎只是为每个 send() 和 recv() 使用一个 while 循环。

于 2020-03-26T23:41:00.487 回答