[英]How do you send a programs current working directory in C using the winsock2 library?
这是我的代码:
#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 端,它是一个字符缓冲区:
char cwd[1024];
getcwd(cwd, sizeof cwd);
send(clientSocket, cwd, sizeof(cwd), 0);
当前目录字符串之后的cwd
缓冲区的内容将是一个 NUL 字节加上堆栈中的随机垃圾,并且整个缓冲区将通过网络发送到 Python 程序。
我最初的建议是只发送尽可能多的有效数据:
send(clientSocket, cwd, strlen(cwd), 0); // don't do this after all
它不发送垃圾,但现在我们发现了另一个问题:接收方期待完整的 1024 字节:
cwd = clientSocket.recv(1024).decode("utf-8").strip()
问题是,发送方传输的字节数要少得多( /home/steve/myproject
的长度或其他),并且由于 TCP 套接字不遵守消息边界,因此它仍在尝试读取完整的 1024。
我怀疑连接重置是因为您的 C 程序在发送后退出,从而关闭了套接字,并且 Python 端在完成接收所有内容之前观察到此关闭。
解决此问题的正确方法可能涉及接收端的超时和缓冲,但这看起来工作量很大,因此我将稍微改变方向。
现在我们将返回发送一个固定大小的缓冲区(如您所建议的 1024),这意味着双方就数据大小达成一致,但您必须修改 Python 端以仅提取字符串的有趣部分,忽略 NUL 字节以及它之后的内容。
在 Python 方面,您仍然会执行cwd = clientSocket.read(1024)
但随后您必须进行缓冲区操作以找出第一个 NUL 字节的位置,并且最多只能使用(但不包括)缓冲区中的字符。
结果子集(例如,47 个字节)将是一个您应该能够解码和使用的字符串。
您的结果可能会因 Python 允许您操作缓冲区并将它们转换为字符串而有所不同; 我不知道。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.