繁体   English   中英

如何使用 winsock2 库在 C 中发送程序当前工作目录?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM