套接字,Unix域UDP c++ recvfrom无法填充源地址
Sockets, Unix Domain UDP C++ recvfrom fail to populate the source address
我试图在c++中创建Android上的unix域套接字服务器和客户端,使用UDP。我需要客户端发送一条消息("hi")到服务器,服务器需要从那里向客户端发送数据。我已经成功地在两端创建了套接字,并且我能够在服务器上接收来自客户机的短消息。但是,服务器上的recvfrom(..)不会填充结构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 ' ' for abstract namespace
const char * socket_name = SOCKET_NAME;
server.sun_path[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 socketn");
return -1;
}
printf("- Socket binding successful on socket path %s len %dn", &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 clientn");
memcpy(&opcode, _messageBuffer, sizeof(opcode)); // I'm getting what I expected
}
但是_clientAddress为空,_clientaddreslength为0。
之后
int result = sendto(_serverSocket
, sendBuf
, sendBufSize
, 0
, (const sockaddr*)&_clientAddress
, _clientAddressLength);
返回1
谢谢你的帮助!
编辑:最后感谢Nikolai N Fetissov的链接和一些挖掘,我使它工作。我想发布一个固定的,100%的双向UDP通信在UNIX域抽象命名空间套接字的工作示例。这是这个http://www.toptip.ca/2013/01/unix-domain-socket-with-abstract-socket.html?m=1链接的一个修复错误的副本。对于未来的几代人来说,因为网络上没有足够的关于这个话题的例子。
server.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;
}
client.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: %dn", integer_buffer);
integer_buffer += 1;
sleep(10);
}
close(socket_fd);
return 0;
}
我希望它有帮助,如果你看到更多的错误,请告诉我
您正在将地址大小参数设置为Internet地址sockaddr_in
的大小,这对于Unix路径来说太小了。
编辑0:
我认为问题在于您没有bind(2)
-ing客户端套接字,因此它没有名称,因此recvfrom(2)
返回零地址长度。
从这里尝试代码(客户端需要与服务器名不同的名称)
相关文章:
- 将数组的地址分配给变量并删除
- OMNET++:如何在INET 4.0中获取帧的源MAC地址?
- 总是引用的地址等于源地址
- 操作员的地址可以启动指针,但填充值是垃圾
- 如何确定 cudaErrorIllegalAddress 是由于目标地址还是源地址
- 阅读UDP广播的源地址
- 如何使用 Poco::Net::HTTPSClientSession 绑定特定的源 IP 地址
- C++填充指向指针**列表的指针,该列表指向指针地址
- 用地址而不是数字填充队列
- 获取传入连接的源 IP 地址
- 列表类,其中填充了返回时丢失地址的指针
- 如何将源IP地址设置为0.0.0.0
- 在 Boost ASIO 中,如何设置源 IP 地址以模拟其他服务器的 IP 地址?
- Solaris 10 -- 从 recvmsg() 的 UDP 组播数据包中获取 IP 源地址
- 如何查找和填充第三方源的 Flash 字段
- 在填充std::矢量时使用不同的地址
- reinterpret_cast保证不更改源指针的地址吗?
- Windows下如何设置UDP源地址
- 套接字,Unix域UDP c++ recvfrom无法填充源地址
- 从路由获取源地址