gpt4 book ai didi

c++ - 套接字,Unix 域 UDP C++ recvfrom 无法填充源地址

转载 作者:太空狗 更新时间:2023-10-29 23:01:08 25 4
gpt4 key购买 nike

我正在尝试使用 UDP 在 C++ 中的 Android 上创建一个 unix 域套接字服务器和客户端。我需要客户端向服务器发送一条消息(“hi”),然后服务器需要从那里向客户端发送数据。我已经成功地在两侧创建了套接字,并且能够在服务器上从客户端接收到一条短消息。然而,服务器上的 recvfrom(..) 不会填充 struct sockaddr *src_addr, socklen_t *addrlen 参数。使用这些 src_addr 和 addrlen 的后续 sendto 消息显然失败了(sendto 返回 -1)。

这是服务器的代码:

int serverSocket = socket(PF_LOCAL, SOCK_DGRAM, 0);
int sendingBufferSize = OUTPUT_BUFFER_SIZE;
setsockopt(serverSocket, SOL_SOCKET, SO_SNDBUF, &sendingBufferSize, sizeof(sendingBufferSize));
struct sockaddr_un server;
memset(&server, 0, sizeof server);
server.sun_family = AF_LOCAL;

// the first byte of sun_path should be '\0' for abstract namespace
const char * socket_name = SOCKET_NAME;
server.sun_path[0] = '\0';
strcpy(server.sun_path + 1, socket_name);
socklen_t sockaddr_len = sizeof(server.sun_family) + strlen(socket_name) + 1;
if (bind(serverSocket, (struct sockaddr *) &server, sockaddr_len) < 0) {
close(serverSocket);
printf("Failed to bind the server socket\n");
return -1;
}

printf("- Socket binding successful on socket path %s len %d\n", &server.sun_path[1], sockaddr_len);

_serverSocket = serverSocket;

稍后我收到来自客户的消息:

int opcode;
_clientAddressLength = sizeof(struct sockaddr_un);
int numOfBytes = recvfrom(_serverSocket, _messageBuffer, INPUT_BUFFER, 0, (struct sockaddr *)&_clientAddress, &_clientAddressLength);
if (numOfBytes != 0)
{
printf("Got a message from client\n");
memcpy(&opcode, _messageBuffer, sizeof(opcode)); // I'm getting what I expected
}

但是 _clientAddress 为空且 _clientAddressLength 设置为 0。

后来

int result = sendto(_serverSocket
, sendBuf
, sendBufSize
, 0
, (const sockaddr*)&_clientAddress
, _clientAddressLength);

返回-1

谢谢大家的帮助!

编辑:

最后感谢 Nikolai N Fetissov 的链接和一些挖掘,我让它工作了。我想发布一个通过 UNIX DOMAIN 抽象命名空间套接字进行双向 UDP 通信的固定 100% 工作示例。这是此 http://www.toptip.ca/2013/01/unix-domain-socket-with-abstract-socket.html?m=1 的拷贝与固定错误链接。对于后代,因为网上没有足够的关于这个主题的例子。

服务器.cpp

#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <string.h>

#include <unistd.h>`

#define SERVER_SOCKET "#UdsServer" // The # is replaced by 0 for abstract namespace

int main(void)
{
int socket_fd;
struct sockaddr_un server_address, client_address;
int bytes_received, bytes_sent, integer_buffer;
socklen_t address_length = sizeof(server_address.sun_family)+strlen(SERVER_SOCKET );

if ((socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
{
perror("server: socket");
return -1;
}

memset(&server_address, 0, sizeof(server_address));
server_address.sun_family = AF_UNIX;
memcpy(server_address.sun_path, SERVER_SOCKET,sizeof(SERVER_SOCKET)-1);// the path is not a C string, and is not NULL turminated
server_address.sun_path[0] = 0;

if (bind(socket_fd,
(const struct sockaddr *) &server_address,
address_length) < 0)
{
perror("server: bind");
close(socket_fd);
return -1;
}

for (;;)
{
bytes_received = recvfrom(socket_fd,
&integer_buffer,
sizeof(integer_buffer),
0,
(struct sockaddr *) &client_address,
&address_length);

if(bytes_received != sizeof(integer_buffer))
{
printf("Error: recvfrom - %d.\n", bytes_received);
} else {
printf("received: %d.\n", integer_buffer);

integer_buffer += 10;

bytes_sent = sendto(socket_fd,
&integer_buffer,
sizeof(integer_buffer),
0,
(struct sockaddr *) &client_address,
address_length);
}
}

close(socket_fd);

return 0;
}

客户端.cpp

#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define SERVER_SOCKET "#UdsServer"
#define CLIENT_SOCKET "#UdsClient"
int main(void)
{
int socket_fd;
struct sockaddr_un server_address, client_address;
int bytes_received, bytes_sent, integer_buffer;
socklen_t address_length = sizeof(server_address.sun_family) + strlen(CLIENT_SOCKET);`

if((socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
{
perror("client: socket");
return -1;
}

memset(&client_address, 0, sizeof(client_address));
client_address.sun_family = AF_UNIX;
memcpy(client_address.sun_path, CLIENT_SOCKET,sizeof(CLIENT_SOCKET )-1 );
client_address.sun_path[0] = 0;

if(bind(socket_fd,
(const struct sockaddr *) &client_address,
address_length) < 0)
{
perror("client: bind");
return -1;
}

memset(&server_address, 0, sizeof(server_address));
server_address.sun_family = AF_UNIX;
memcpy(server_address.sun_path, SERVER_SOCKET,sizeof(SERVER_SOCKET)-1);
server_address.sun_path[0] = 0;

integer_buffer = 1;

for (;;)
{
bytes_sent = sendto(socket_fd,
&integer_buffer,
sizeof(integer_buffer),
0,
(struct sockaddr *) &server_address,
address_length);

bytes_received = recvfrom(socket_fd,
&integer_buffer,
sizeof(integer_buffer),
0,
(struct sockaddr *) &server_address,
&address_length);

if (bytes_received != sizeof(integer_buffer))
{
printf("Error: recvfrom - %d.\n", bytes_received);
return -1;
}

printf("received: %d\n", integer_buffer);

integer_buffer += 1;

sleep(10);
}

close(socket_fd);

return 0;
}

希望对您有所帮助,如果您发现更多错误,请告诉我

最佳答案

您正在将地址大小参数设置为互联网地址 sockaddr_in 的大小,这对于 Unix 路径来说太小了。

编辑0:

我认为问题在于您没有bind(2)-ing 客户端套接字,因此它没有名称,因此recvfrom(2) 返回地址长度为零。

尝试来自 here 的代码(客户端需要一个不同于服务器名称的名称)。

关于c++ - 套接字,Unix 域 UDP C++ recvfrom 无法填充源地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31755790/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com