简体   繁体   English

C ++ Unix Socket捕获系统调用

[英]C++ Unix Socket capturing system calls

I am attempting to monitor a long running daemon using a monitoring application which creates a UNIX socket and listens. 我正在尝试使用监视应用程序来监视长时间运行的守护程序,该应用程序会创建UNIX套接字并进行监听。 In testing, however, I have found that calls I am making to the system on other threads within the application are showing up in this socket. 但是,在测试中,我发现我正在应用程序内其他线程上对系统的调用正在此套接字中显示。

// 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

The long running daemon is already created and outputs to a socket if available. 长时间运行的守护程序已经创建,并输出到套接字(如果有)。 At the moment it is just writting "test" to the socket every second. 目前,它只是每秒在套接字上编写“测试”。

// 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;
}

I have pasted together a quick server application to test that everything was working correctly, so the code is very rough. 我已经粘贴了一个快速的服务器应用程序来测试一切是否正常运行,因此代码很粗糙。

/* 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);
}

I'm not certain how the calls are being introduced to the socket. 我不确定如何将调用引入套接字。 There are no sockets used anywhere else in this application. 在此应用程序的其他任何地方都没有使用套接字。 Is there a buffer that I should be clearing before writting or reading from the socket? 在写套接字或从套接字读取之前,是否应该清除缓冲区?

Portion from strace output. 来自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

It appears to be like the message is being read in correctly. 好像是在正确读取该消息。 I will work on parsing the output from the daemon's strace to see if it uncovers anything. 我将解析守护程序的strace的输出,以查看它是否发现了任何东西。

UPDATE I was not able to determine the source of this issue. 更新我无法确定此问题的根源。 I rewrote all system calls to output to /dev/null and still received the warning and error messages in the socket. 我将所有系统调用重写为输出到/dev/null并且仍然在套接字中收到警告和错误消息。 I attempted to switch to a TCP socket but encountered the same issue. 我试图切换到TCP套接字,但是遇到了同样的问题。 strace didn't reveal any send or write calls on the socket that would lead to these calls appearing. strace没有显示任何在套接字上的发送或写入调用,这些调用或调用会导致这些调用出现。

Eventual solution was to use telnet and ANSI controls to constantly rewrite telnet output to mask warning messages. 最终的解决方案是使用telnet和ANSI控件不断重写telnet输出以屏蔽警告消息。

The problem is not with the buffer and the chance is minimal that some other part of the program is writing to your buffer, since the buffer is allocated on stack. 问题不在于缓冲区,程序的其他部分正在写入缓冲区的机会很小,因为缓冲区是在堆栈上分配的。 It seems that the message is received on the socket, but is strange for a normal Linux that the socket fd=3, you don't have any open files? 似乎在套接字上收到了该消息,但是对于普通Linux来说,套接字fd = 3奇怪,您没有任何打开的文件吗?

For example: 例如:

nbytes = recv(connection_fd, buffer, 256, 0)
buffer[nbytes] = \0;

When nbytes is 256 you are writing outside the buffer, which can cause even segmentation faults. 当nbytes为256时,您正在缓冲区外写入​​数据,这甚至可能导致分段错误。

connection_fd = accept(sockfd, (struct sockaddr *) &serv_addr, &address_length)

Overwriting server address, it should be cli_addr probably 覆盖服务器地址,可能应该是cli_addr

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM