【问题标题】:C and Python - communicating with socketsC 和 Python - 与套接字通信
【发布时间】:2011-10-12 04:16:05
【问题描述】:

我正在尝试使用 UNIX 域套接字在 C 程序和 Python 脚本之间进行通信。 Python 脚本通过 UNIX 域套接字将数据发送到 C 程序。

这是我的 C 程序中的相关代码:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/un.h>
#include <sys/types.h>
#include <sys/socket.h>    
#define UNIX_PATH_MAX 100

int main(void)
{
struct sockaddr_un address;
int socket_fd, connection_fd;
socklen_t address_length;
pid_t child;

socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (socket_fd < 0){
    printf("socket() failed\n");
    return 1;
} 

unlink("/tmp/demo_socket");
memset(&address, 0, sizeof(struct sockaddr_un));

address.sun_family = AF_UNIX;
snprintf(address.sun_path, UNIX_PATH_MAX, "/tmp/demo_socket");

if (bind(socket_fd, (struct sockaddr *) &address, sizeof(struct sockaddr_un)) != 0) {
    printf("bind() failed\n");
    return 1;
}
if(listen(socket_fd, 5) != 0) {
    printf("listen() failed\n");
    return 1;
}

//----------------WHILE LOOP----------------------->
while((connection_fd = accept(socket_fd, 
                            (struct sockaddr *) &address,
                            &address_length)) > -1)
{
.
.
.(doesn't get any further than this)

这是我用来向套接字发送消息的 python 脚本:

import socket

s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect("/tmp/demo_socket")
print "Sending..."
s.send("Hello world")
x = s.recv(1024)
print x
s.close()

python 脚本失败并出现错误“Broken Pipe”。 C 程序永远不会进入 while 循环,因为 accept() 函数失败并返回“-1”。

为什么 accept() 失败了?我该怎么做才能让它成功?

【问题讨论】:

  • 当接受失败时,在您的 C 代码中打印出errno(或更好:strerror(errno))。那和手册页应该至少告诉你部分答案。
  • 它因错误“无效参数”而失败。

标签: python c sockets unix dns


【解决方案1】:

IIRC,address_length 需要在调用accept() 之前初始化为sockaddr_un 的大小。在调用过程中,它会加载推入address 的对等地址的实际长度。

Rgds, 马丁

【讨论】:

  • 太棒了!在阅读了您的提示并进行了一些谷歌搜索后,我通过设置提出了一个解决方案: address_length = sizeof(address);在我的 accept() 电话之前。谢谢!
【解决方案2】:

查看an example I found,您传递的bind 的长度似乎不应计入sockaddr_un 中的终止或填充空值。

试试:

size_t addrlen;
const char* sockname = "/tmp/demo_socket";

/* ... */

address.sun_family = AF_UNIX;
snprintf(address.sun_path, UNIX_PATH_MAX, sockname);
addrlen = sizeof(address.sun_family) + strlen(sockname);

if (bind(socket_fd, (struct sockaddr *) &address, addrlen) != 0) {
    printf("bind() failed\n");
    return 1;
}

附:因此,您不需要memset 调用。

【讨论】:

  • 嗨@mike,链接似乎已损坏...您能修复它吗?
  • 此时它可能已经消失了。我将链接保留在那里,因为它不是我的原创作品,但是已经很久了,我不确定我能找到更好的链接。在任何情况下,答案都不需要链接。
猜你喜欢
  • 1970-01-01
  • 2020-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多