[英]C++ Unix Socket capturing system calls
我正在嘗試使用監視應用程序來監視長時間運行的守護程序,該應用程序會創建UNIX套接字並進行監聽。 但是,在測試中,我發現我正在應用程序內其他線程上對系統的調用正在此套接字中顯示。
// Output from Server Test Application (just echoing from recv buffer)
# serverTest /tmp/receiver-programmer-socket
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: PING 192.168.1.51 (192.168.1.51): 56 data bytes
--- 192.168.1.51 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
MESSAGE FROM CLIENT: PING 192.168.1.52 (192.168.1.52): 56 data bytes
--- 192.168.1.52 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: PING 192.168.1.51 (192.168.1.51): 56 data bytes
--- 192.168.1.51 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
MESSAGE FROM CLIENT: PING 192.168.1.52 (192.168.1.52): 56 data bytes
--- 192.168.1.52 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
長時間運行的守護程序已經創建,並輸出到套接字(如果有)。 目前,它只是每秒在套接字上編寫“測試”。
// Long Running Daemon Snippet
int Monitor::write_to_socket(){
std::string string = "test";
char buffer[1024];
bzero(buffer, sizeof(buffer));
strcpy(buffer, string.c_str());
if (send(sockfd, buffer, strlen(buffer), MSG_NOSIGNAL) < 0)
{
syslog(LOG_INFO, "Error sending to socket");
close(sockfd);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
我已經粘貼了一個快速的服務器應用程序來測試一切是否正常運行,因此代碼很粗糙。
/* a server in the unix domain. The pathname of
the socket address is passed as an argument */
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/un.h>
#include <stdio.h>
void error(const char *);
int connection_handler(int);
int main(int argc, char *argv[])
{
// File descriptors
int sockfd, newsockfd;
// Length of address string
int servlen;
//
int n;
// Size of client address
socklen_t clilen;
// Client socket address
struct sockaddr_un cli_addr;
// Server socket address
struct sockaddr_un serv_addr;
// Character buffer
char buf[80];
// Create socket
if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
error("creating socket");
// Sets server address area to all zeros
bzero((char *)&serv_addr, sizeof(serv_addr));
// Sets server address family to local interprocess
serv_addr.sun_family = AF_UNIX;
// Sets server address path to passed in argument
strcpy(serv_addr.sun_path, argv[1]);
// Sets length of full server address
servlen = strlen(serv_addr.sun_path) + sizeof(serv_addr.sun_family);
// Bind socket at address and port (sortof)
if (bind(sockfd, (struct sockaddr *)&serv_addr, servlen) < 0)
error("binding socket");
// Start listening for requests
listen(sockfd, 5);
pid_t child;
int connection_fd;
socklen_t address_length;
while((connection_fd = accept(sockfd, (struct sockaddr *) &serv_addr, &address_length)) > -1)
{
child = fork();
if(child == 0)
{
/* now inside newly created connection handling process */
return connection_handler(connection_fd);
}
/* still inside server process */
close(connection_fd);
}
return 0;
}
int connection_handler(int connection_fd)
{
int nbytes;
char buffer[256];
while(1) {
bzero((char *)&buffer, sizeof(buffer));
// Corrected to test for correct return and buffer size
if((nbytes = recv(connection_fd, buffer, 256, 0)) > 0)
{
buffer[nbytes] = 0;
printf("MESSAGE FROM CLIENT: %s\n", buffer);
}
}
close(connection_fd);
return 0;
}
void error(const char *msg)
{
perror(msg);
exit(0);
}
我不確定如何將調用引入套接字。 在此應用程序的其他任何地方都沒有使用套接字。 在寫套接字或從套接字讀取之前,是否應該清除緩沖區?
來自strace
輸出的部分。
[pid 15286] close(4) = 0
[pid 15286] accept(3, <unfinished ...>
[pid 15296] recv(4, "test", 256, 0) = 4
[pid 15296] fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
[pid 15296] mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40001000
[pid 15296] write(1, "MESSAGE FROM CLIENT: test\n", 26MESSAGE FROM CLIENT: test
) = 26
[pid 15296] recv(4, "PING 192.168.1.50 (192.168.1.50)"..., 256, 0) = 103
[pid 15296] write(1, "MESSAGE FROM CLIENT: PING 192.16"..., 124MESSAGE FROM CLIENT: PING 192.168.1.50 (192.168.1.50): 56 data bytes
64 bytes from 192.168.1.50: seq=0 ttl=64 time=2.156 ms
) = 124
[pid 15296] write(1, "\n", 1
) = 1
[pid 15296] recv(4, "\n--- 192.168.1.50 ping statistic"..., 256, 0) = 142
[pid 15296] write(1, "MESSAGE FROM CLIENT: \n--- 192.16"..., 163MESSAGE FROM CLIENT:
--- 192.168.1.50 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 2.156/2.156/2.156 ms
) = 163
[pid 15296] write(1, "\n", 1
) = 1
[pid 15296] recv(4, "PING 192.168.1.50 (192.168.1.50)"..., 256, 0) = 103
[pid 15296] write(1, "MESSAGE FROM CLIENT: PING 192.16"..., 124MESSAGE FROM CLIENT: PING 192.168.1.50 (192.168.1.50): 56 data bytes
64 bytes from 192.168.1.50: seq=0 ttl=64 time=2.063 ms
) = 124
好像是在正確讀取該消息。 我將解析守護程序的strace的輸出,以查看它是否發現了任何東西。
更新我無法確定此問題的根源。 我將所有系統調用重寫為輸出到/dev/null
並且仍然在套接字中收到警告和錯誤消息。 我試圖切換到TCP套接字,但是遇到了同樣的問題。 strace
沒有顯示任何在套接字上的發送或寫入調用,這些調用或調用會導致這些調用出現。
最終的解決方案是使用telnet和ANSI控件不斷重寫telnet輸出以屏蔽警告消息。
問題不在於緩沖區,程序的其他部分正在寫入緩沖區的機會很小,因為緩沖區是在堆棧上分配的。 似乎在套接字上收到了該消息,但是對於普通Linux來說,套接字fd = 3奇怪,您沒有任何打開的文件嗎?
例如:
nbytes = recv(connection_fd, buffer, 256, 0)
buffer[nbytes] = \0;
當nbytes為256時,您正在緩沖區外寫入數據,這甚至可能導致分段錯誤。
connection_fd = accept(sockfd, (struct sockaddr *) &serv_addr, &address_length)
覆蓋服務器地址,可能應該是cli_addr
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.