守护进程套接字在后台请求

时间:2013-09-23 14:20:02

标签: c++ linux sockets

我有两个流程:daemonclient。两者都是不同的插座。最初我执行deamon socket ./daemon然后./client

但我希望守护进程应该始终在后台监听来自客户端的请求。所以使用fork()我尝试创建这样一个过程。

我刚编辑了原始代码。

现在我可以编译守护程序文件并创建可执行文件daemon

但是当我发送请求./client时,它没有回应。并说error connecting socket 111

daemon正在监听1104并且客户端发送请求。 当我说出./daemonError binding to socket, make sure nothing else is listening on this port 22n

表示它在后台运行但未按要求响应。 代码:

#include <fcntl.h>
#include <string.h>
#include <algorithm>

#include "dictionary_exclude.h"
#pragma GCC diagnostic ignored "-Wwrite-strings"

#define CHECK_THROW(condition, code) if(condition) throw code
void *SocketHandler(void *);
int OpenSocket();
int main(int argv, char **argc)
{
    int host_port = 1104;
    char buf[20];
    int k;
    struct sockaddr_in my_addr;
    int hsock;
    int *p_int;
    int err;
    socklen_t addr_size = 0;
    int *csock;
    sockaddr_in sadr;
    pthread_t thread_id = 0;

    try {
    pid_t pid = fork();
    CHECK_THROW(pid < 0, -5);
    if (pid == 0) {
        mode_t umask(mode_t mask);
        pid_t childid = setsid();

        hsock = OpenSocket();   // Function call for hsock
        CHECK_THROW(listen(hsock, 10) == -1, -4);
        my_addr.sin_family = AF_INET;
        my_addr.sin_port = htons(host_port);

        memset(&(my_addr.sin_zero), 0, 8);
        my_addr.sin_addr.s_addr = INADDR_ANY;

        if (bind(hsock, (sockaddr *) & my_addr, sizeof(my_addr)) == -1) {
        fprintf(stderr, "Error binding to socket, make sure nothing else is listening on this port %dn", errno);
        exit(EXIT_SUCCESS);
        }
        if (listen(hsock, 10) == -1) {
        fprintf(stderr, "Error listening %dn", errno);
        exit(EXIT_SUCCESS);
        }
        //Now lets do the server stuff

        addr_size = sizeof(sockaddr_in);

        while (true) {
        printf("waiting for a connectionnn");
        csock = (int *) malloc(sizeof(int));
        if ((*csock = accept(hsock, (sockaddr *) & sadr, &addr_size)) != -1) {
            printf("---------------------nReceived connection from %sn", inet_ntoa(sadr.sin_addr));
            pthread_create(&thread_id, 0, &SocketHandler, (void *) csock);
            pthread_detach(thread_id);
        } else {
            fprintf(stderr, "Error accepting %dn", errno);
        }
        }           //while end
    }           //if (pid) end
    }               //try

    catch(int ierror) {
    switch (ierror) {
    case -4:
        fprintf(stderr, "Error listening %dn", errno);
        break;
    case -7:
        fprintf(stderr, "Error accepting %dn", errno);
        break;
    }
    }

}

int OpenSocket()
{
    // Create your socket and return the socket handle from this function 
    int hsock;
    int *p_int;
    hsock = socket(AF_INET, SOCK_STREAM, 0);
    if (hsock == -1) {
    printf("Error initializing socket %dn", errno);
    exit(EXIT_SUCCESS);
    }

    p_int = (int *) malloc(sizeof(int));
    *p_int = 1;

    if ((setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char *) p_int, sizeof(int)) == -1) || (setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char *) p_int, sizeof(int)) == -1)) {
    printf("Error setting options %dn", errno);
    free(p_int);
    exit(EXIT_SUCCESS);
    }
    free(p_int);
    return hsock;
}


void *SocketHandler(void *lp)
{

    //some procesing
}

有人可以说上面的代码有问题吗。

原始代码是:

int main(int argv, char **argc)
{
    int host_port = 1104;
    char buf[20];
    int k;
    struct sockaddr_in my_addr;
    int hsock;
    int *p_int;
    int err;
    socklen_t addr_size = 0;
    int *csock;
    sockaddr_in sadr;
    pthread_t thread_id = 0;

    try {
    pid_t pid = fork();
    CHECK_THROW(pid < 0, -5);
    if (pid == 0) {
        mode_t umask(mode_t mask);
        pid_t childid = setsid();

        hsock = OpenSocket();   // Function call for hsock
        CHECK_THROW(listen(hsock, 10) == -1, -4);
        my_addr.sin_family = AF_INET;
        my_addr.sin_port = htons(host_port);

        memset(&(my_addr.sin_zero), 0, 8);
        my_addr.sin_addr.s_addr = INADDR_ANY;

        if (bind(hsock, (sockaddr *) & my_addr, sizeof(my_addr)) == -1) {
        fprintf(stderr, "Error binding to socket, make sure nothing else is listening on this port %dn", errno);
        exit(EXIT_SUCCESS);
        }
        if (listen(hsock, 10) == -1) {
        fprintf(stderr, "Error listening %dn", errno);
        exit(EXIT_SUCCESS);
        }
        //Now lets do the server stuff

        addr_size = sizeof(sockaddr_in);

        while (true) {
        printf("waiting for a connectionnn");
        csock = (int *) malloc(sizeof(int));
        if ((*csock = accept(hsock, (sockaddr *) & sadr, &addr_size)) != -1) {
            printf("---------------------nReceived connection from %sn", inet_ntoa(sadr.sin_addr));
            pthread_create(&thread_id, 0, &SocketHandler, (void *) csock);
            pthread_detach(thread_id);
        } else {
            fprintf(stderr, "Error accepting %dn", errno);
        }
        }           //while end
    }           //if (pid) end
    }               //try

    catch(int ierror) {
    switch (ierror) {
    case -4:
        fprintf(stderr, "Error listening %dn", errno);
        break;
    case -7:
        fprintf(stderr, "Error accepting %dn", errno);
        break;
    }
    }

}

int OpenSocket()
{
    // Create your socket and return the socket handle from this function 
    int hsock;
    int *p_int;
    hsock = socket(AF_INET, SOCK_STREAM, 0);
    if (hsock == -1) {
    printf("Error initializing socket %dn", errno);
    exit(EXIT_SUCCESS);
    }

    p_int = (int *) malloc(sizeof(int));
    *p_int = 1;

    if ((setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char *) p_int, sizeof(int)) == -1) || (setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char *) p_int, sizeof(int)) == -1)) {
    printf("Error setting options %dn", errno);
    free(p_int);
    exit(EXIT_SUCCESS);
    }
    free(p_int);
    return hsock;
}

void *SocketHandler(void *lp)
{

    //some procesing
}

2 个答案:

答案 0 :(得分:2)

您在致电listen之前致电bind - 您应先致电bind

实际上,在调用listen之前和之后,您都在调用bind两次。删除第一个电话。

hsock = OpenSocket();
// remove this line:
CHECK_THROW(listen(hsock, 10) == -1, -4); 
my_addr.sin_family = AF_INET;

另一项改进:使用strerrorperror生成错误消息,以便您获得用户友好的消息。例如:

perror("Error binding to socket");
exit(EXIT_SUCCESS);

答案 1 :(得分:0)

解决方案非常简单: 不需要大编码,只需&即可完成所有操作。

取代执行./daemon使用./daemon &。这将使守护进程继续监听