这是我的密码:
#include <stdio.h>
#include <unistd.h>
#include <windows.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
int main(){
WSADATA wsa;
WSAStartup(MAKEWORD(2, 2), &wsa);
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in serverAddr, clientAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(6969);
serverAddr.sin_addr.s_addr = INADDR_ANY;
bind(serverSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
listen(serverSocket, 1);
int s_size = sizeof(struct sockaddr_in);
SOCKET clientSocket = accept(serverSocket, (struct sockaddr *)&clientAddr, &s_size);
char cwd[1024];
getcwd(cwd, 1024);
printf(cwd);
send(clientSocket, cwd, sizeof(cwd), 0);
return 0;
}
它的目的是将程序的cwd发送到python脚本,但是每当我运行python脚本时,当它接收到cwd时,就会出现以下错误:
cwd = clientSocket.recv(1024).decode("utf-8").strip()
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd4 in position 44: invalid continuation byte
每当我在C程序上打印cwd时,它都会毫无问题地打印出来。 我尝试过如下方式终止字符串:
cwd[strlen(cwd)] = 0;
它没有改变任何事情
我最好的猜测是,实际路径和空终止符之间的数据是导致python脚本端编码错误的原因,但是我无法为路径分配足够的内存,因为在分配内存之前我无法知道路径的长度,所以我选择了1024,因为我觉得这是一个合理的值
有人知道我怎么解决这个问题吗
编辑: 我解决了。由于缓冲区大(1024),cwd字符串和实际字符串中有很多垃圾。我设法为cwd分配内存,并将其重新分配到strlen()
char *cwd = malloc(1024*sizeof(char));
getcwd(cwd, 1024);
realloc(cwd, strlen(cwd));
printf(cwd);
send(clientSocket, cwd, strlen(cwd), 0);
这对我有用
我不懂Python,但相信我看到了这里发生的事情:这似乎是两种不同的处理字符串的方法之间的阻抗不匹配。这需要几个步骤
在C端,它是一个字符缓冲区:
当前目录字符串之后的
cwd
缓冲区的内容将是一个NUL字节加上堆栈中的随机垃圾,整个缓冲区将通过网络发送到Python程序我最初的建议是只发送有效的数据:
它不发送垃圾,但现在我们发现另一个问题:接收端需要1024字节:
问题是,发送方传输的字节要少得多(长度为
/home/steve/myproject
或其他什么),而且由于TCP套接字不遵守消息边界,因此它仍在尝试读取完整的1024字节我怀疑连接重置是因为您的C程序在发送之后退出,这会关闭套接字,Python端在接收完所有内容之前观察到这个关闭
解决这个问题的正确方法可能涉及接收端的超时和缓冲,但是这看起来需要做很多工作,所以我会稍微改变一下方向
现在我们将返回到发送一个固定大小的缓冲区(如您所建议的1024),这意味着双方都同意数据大小,但是您必须修改Python端,以便只提取字符串中感兴趣的部分,而忽略NUL字节及其以外的内容
在Python方面,您仍然需要执行
cwd = clientSocket.read(1024)
,但是接下来必须执行缓冲区操作以找出第一个NUL字节的位置,并且只能在缓冲区中使用最多(但不包括)该字符得到的子集(比如47字节)将是一个您应该能够解码和使用的字符串
根据Python如何操作缓冲区并将它们转换为字符串,结果可能会有所不同;我不知道
相关问题 更多 >
编程相关推荐