c++ - 无法打印客户端 sun_path unix domain socket
问题描述
这是我正在使用的 UNIX 域服务器和客户端代码。服务器和客户端通过相互接收消息来相互发送消息。
服务器代码通过填充 client_address 从 recvfrom 向客户端发送消息。此外,您可以看到这个 unix 域套接字代码使用抽象命名系统。服务器命名为 UnixServer,客户端命名为 UnixClient。如果服务器可以通过填充其 client_address 向客户端发送消息,我想看看那个地址是什么。这是一个有意义的地址吗?我可以将其打印为#UdsClient 等吗?
服务器代码:
#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);
struct sockaddr_storage ss;
socklen_t sslen = sizeof(struct sockaddr_storage);
if (getsockname(socket_fd, (struct sockaddr *)&ss, &sslen) == 0) {
struct sockaddr_un *un = (struct sockaddr_un *)&ss;
printf("socket name is: %s\n", un->sun_path);
}
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);
//printf("clientaddress: %s", client_address.sa_data);
}
}
close(socket_fd);
return 0;
}
客户代码:
#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);
printf("clientaddress: %s", server_address.sun_path);
bytes_received = recvfrom(socket_fd,
&integer_buffer,
sizeof(integer_buffer),
0,
(struct sockaddr *) &server_address,
&address_length);
printf("clientaddress: %s", server_address.sun_path);
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;
}
此外,我尝试使用这些代码行打印它,但它什么也没打印:
struct sockaddr_storage ss;
socklen_t sslen = sizeof(struct sockaddr_storage);
if (getsockname(socket_fd, (struct sockaddr *)&ss, &sslen) == 0) {
struct sockaddr_un *un = (struct sockaddr_un *)&ss;
printf("socket name is: %s\n", un->sun_path);
}
我在做什么错如何打印#UdsClient,或任何其他含义完整的东西?
编辑,我的解决方案
我相信这是一个相对容易的问题。而不是最后一段代码,我可以如下阅读它:
printf("socket name is: #%s\n", client_address.sun_path + 1);
因此路径被填充,但是由于第一个字母为空,因此无法直接打印出来。
您也可以将此方法用于非抽象文件路径系统。
解决方案
当您%s
用作格式说明符时,printf
它将关联的参数视为以空字符结尾的字符数组。但是,您通过设置来使用抽象套接字...
server_address.sun_path[0] = 0;
因此printf
将被视为零长度字符串——它对紧接在该前导空字符之后server_address.sun_path
的数据一无所知。
推荐阅读
- python - 在 python 中的某个时间限制后终止并在 ILOG 中检索解决方案
- guid - 如何使用 Java 从 BMC Remedy 用户获取用户 ID 或 GUID
- html - 表格行隐藏在导航栏下
- flutter - Javascript“2020 年 2 月 15 日星期六 14:01:19 GMT+0300(东非时间)”颤动的日期格式类型
- python - Python Regex - 用另一个单词替换特定单词(没有哈希)
- firebase-realtime-database - ESP8266 无法从 Google Firebase 读取数据
- python - Python 列表乘法
- python - 反向链表 - 如何删除(输出)末尾的“无”
- c# - 自定义 Xamarin.Forms.Datepicker 以选择和可视化多个日期
- java - 在 JavaFX 中格式化动态添加的标签