popen无法使用外部库

时间:2019-01-20 12:52:57

标签: c opencv server popen

我有一个使用C的应用程序服务器和客户端(代码摘自Unix环境中的Advanced Programming)。

当客户端连接时,服务器正在调用函数popen以执行另一个程序,创建管道并通过该管道读取其输出。

对于我来说,SELECT Scorer ,CASE WHEN PATINDEX('%(%)%',Scorer) > 1 THEN LEFT(Scorer, PATINDEX('%(%)%',Scorer)-1) ELSE RIGHT (Scorer, LEN(Scorer) - CHARINDEX(')',Scorer,1) ) END AS ColumnName FROM ScoreTable 启动的程序是该文件的编译结果:

popen

服务器-客户端应用程序可以与上述代码的程序一起正常工作,但是如果我建议#include<iostream> #ifndef __OPENCV__ #define __OPENCV__ //#include "opencv2/opencv.hpp" #endif int main(int argc, char *argv[]) { std::cout<<"hello\n"; return 0; } 不再起作用,则可以直接从终端启动它,但是我需要#include "opencv2/opencv.hpp"库文件在启动之前(这是原因?如果可以,怎么办?)。

可以在here中找到服务器-客户端程序,并且可以仅在主目录中运行export来对其进行编译(由make运行的可执行文件的路径可以更改)。客户端和服务器程序是名称中带有popen的程序。如果在Ubuntu上,您可以直接使用可执行文件,但是上面的文件应使用输出名称connectionless进行编译,然后放在桌面上。

server.c

openCV

客户代码

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<netdb.h> //Here are defined AF_INET and the others of the family
#include<syslog.h> //LOG_ERR
#include<errno.h> //errno
#include <sys/types.h>
#include <sys/wait.h>

#include"../common/utilities.h"
#include "error.h"

#define BUFLEN 128
#define QLEN 10
#define MAXADDRLEN 256
#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 156
#endif

int initserver(int type, const struct sockaddr *addr, socklen_t alen, int qlen);

void serve(int sockfd);
void serve2(int sockfd);
void serveConnectionless(int sockfd);

int main(int argc, char* argv[])
{
    printf("entered main\n");
    struct addrinfo *ailist, *aip, hint;
    int sockfd, err, n;
    char *host;
    if (argc != 1)
    {
        printf("usage: ruptimed\n");
        exit(1);
    }
    /*
      sysconf: get configuration information at run time
      HOST_NAME_MAX - _SC_HOST_NAME_MAX
      Maximum length of a hostname, not including the terminating
      null byte, as returned by gethostname(2).  Must not be less
      than _POSIX_HOST_NAME_MAX (255).*/
    if ((n = sysconf(_SC_HOST_NAME_MAX))<0)
    {
        n = HOST_NAME_MAX;
    }
    if((host = malloc(n)) == NULL)
    {
        printf("malloc error\n");
        exit(1);
    }
    if (gethostname(host, n)<0)
    {
        printf("gethostname error\n");
        exit(1);
    }
    printf("Daemonizing\n");
    daemonize("ruptimed");
    /*       The hints argument points to an addrinfo structure that specifies
       criteria for selecting the socket address structures returned in the
       list pointed to by res.  If hints is not NULL it points to an
       addrinfo structure whose ai_family, ai_socktype, and ai_protocol
       specify criteria that limit the set of socket addresses returned by
       getaddrinfo(), as follows:

       ai_family   This field specifies the desired address family for the
                   returned addresses.  Valid values for this field include
                   AF_INET and AF_INET6.  The value AF_UNSPEC indicates that
                   getaddrinfo() should return socket addresses for any
                   address family (either IPv4 or IPv6, for example) that
                   can be used with node and service.

       ai_socktype This field specifies the preferred socket type, for exam‐
                   ple SOCK_STREAM or SOCK_DGRAM.  Specifying 0 in this
                   field indicates that socket addresses of any type can be
                   returned by getaddrinfo().

       ai_protocol This field specifies the protocol for the returned socket
                   addresses.  Specifying 0 in this field indicates that
                   socket addresses with any protocol can be returned by
                   getaddrinfo().

       ai_flags    This field specifies additional options, described below.
                   Multiple flags are specified by bitwise OR-ing them
                   together.

       All the other fields in the structure pointed to by hints must con‐
       tain either 0 or a null pointer, as appropriate.*/
    memset(&hint, 0, sizeof(hint)); 
    hint.ai_flags |= AI_PASSIVE;
    hint.ai_socktype = SOCK_DGRAM;
    hint.ai_addr = NULL;
    hint.ai_next = NULL;
    /*If the AI_PASSIVE flag is specified in hints.ai_flags, and node is
       NULL, then the returned socket addresses will be suitable for
       binding a socket that will accept(2) connections.  The returned
       socket address will contain the "wildcard address" (INADDR_ANY for
       IPv4 addresses, IN6ADDR_ANY_INIT for IPv6 address).  The wildcard
       address is used by applications (typically servers) that intend to
       accept connections on any of the host's network addresses.  If node
       is not NULL, then the AI_PASSIVE flag is ignored.

       If the AI_PASSIVE flag is not set in hints.ai_flags, then the
       returned socket addresses will be suitable for use with connect(2),
       sendto(2), or sendmsg(2).  If node is NULL, then the network address
       will be set to the loopback interface address (INADDR_LOOPBACK for
       IPv4 addresses, IN6ADDR_LOOPBACK_INIT for IPv6 address); this is used
       by applications that intend to communicate with peers running on the
       same host.

       Service sets the port in each returned address structure.  If this
       argument is a service name (see services(5)), it is translated to the
       corresponding port number.  This argument can also be specified as a
       decimal number, which is simply converted to binary.  If service is
       NULL, then the port number of the returned socket addresses will be
       left uninitialized.  If AI_NUMERICSERV is specified in hints.ai_flags
       and service is not NULL, then service must point to a string contain‐
       ing a numeric port number.  This flag is used to inhibit the invoca‐
       tion of a name resolution service in cases where it is known not to
       be required.

       Either node or service, but not both, may be NULL.*/
    if((err = getaddrinfo(NULL, "60185", &hint, &ailist))!=0)
    {
        printf("Error line 129 %d\n", err);
        syslog(LOG_ERR, "ruptimed: getaddrinfo error %s", gai_strerror(err));
        exit(1);
    }
    for (aip = ailist; aip!=NULL; aip = aip->ai_next)
    {
        if ((sockfd = initserver(SOCK_DGRAM, aip->ai_addr, aip->ai_addrlen, QLEN))>=0)
        {
            //printf("starting to serve\n");
            serveConnectionless(sockfd);
            printf("Exiting \n");
            exit(0);
        }
    }
    exit(1);
}


void serveConnectionless(int sockfd)
{
    int n;
    socklen_t alen;
    FILE *fp;
    char buf[BUFLEN];
    char abuf[MAXADDRLEN];
    struct sockaddr *addr = (struct sockaddr*)abuf;
    for(;;)
    {
        alen = MAXADDRLEN;
        if((n=recvfrom(sockfd, buf, BUFLEN, 0, addr, &alen))<0)
        {
            syslog(LOG_ERR, "ruptimed: recvfrom error %s", strerror(errno));
            exit(1);
        }
        /**pg. 542 Since a common operation is to create a pipe to another process
        to either read its output or write its input stdio has provided popen and
        pclose: popen creates pipe, close the unused ends of the pipe,
        forks a child and call exec to execute cmdstr and
        returns a file pointer (connected to std output if "r", to stdin if "w").
        pclose closes the stream, waits for the command to terminate*/
        if ((fp = popen("/home/usr/Desktop/openCV", "r")) == NULL)
        {
            /*sprintf copy the string passed as second parameter inside buf*/
            sprintf(buf, "error: %s\n", strerror(errno));
            /*pag 610. send is similar to write. send(int sockfd, const void *buf, size_t nbytes, it flags)*/
            //send(clfd, buf, strlen(buf),0);
            sendto(sockfd, buf, strlen(buf),0, addr, alen);
        }
        else
        {
            /*get data from the pipe that reads created to exec /usr/bin/uptime */
            if(fgets(buf, BUFLEN, fp)!=NULL)
            {
                sendto(sockfd, buf, strlen(buf),0, addr, alen);
            }
            /*see popen pag. 542*/
            pclose(fp);
        }
        //close(clfd);
    }
}


void serve(int sockfd)
{
    int clfd;
    FILE *fp;
    char buf[BUFLEN];
    set_cloexec(sockfd);
    for(;;)
    {
        /*After listen, the socket can receive connect requests. accept
        retrieves a connect request and converts it into a connection.
        The file returned by accept is a socket descriptor connected to the client that
        called connect, haing the same coket type and family type. The original
        soket remains available to receive otherconneion requests. If we don't care
        about client's identity we can set the second (struct sockaddr *addr)
        and third parameter (socklen_t *len) to NULL*/
        if((clfd = accept(sockfd, NULL, NULL))<0)
        {
            /*This generates a log mesage.
            syslog(int priority, const char *fformat,...)
            priority is a combination of facility and level. Levels are ordered from highest to lowest:
            LOG_EMERG: emergency system unusable
            LOG_ALERT: condiotin that must be fied immediately
            LOG_CRIT: critical condition
            LOG_ERR: error condition
            LOG_WARNING
            LOG_NOTICE
            LOG_INFO
            LOG_DEBUG
            format and other arguements are passed to vsprintf function forf formatting.*/
            syslog(LOG_ERR, "ruptimed: accept error: %s", strerror(errno));
            exit(1);
        }
        /* set the FD_CLOEXEC file descriptor flag */
        /*it causes the file descriptor to be automatically and atomically closed
         when any of the exec family function is called*/
        set_cloexec(clfd);
        /**pg. 542 Since a common operation is to create a pipe to another process
        to either read its output or write its input stdio has provided popen and
        pclose: popen creates pipe, close the unused ends of the pipe,
        forks a child and call exec to execute cmdstr and
        returns a file pointer (connected to std output if "r", to stdin if "w").
        pclose closes the stream, waits for the command to terminate*/
        if ((fp = popen("/usr/bin/uptime", "r")) == NULL)
        {
            /*sprintf copy the string passed as second parameter inside buf*/
            sprintf(buf, "error: %s\n", strerror(errno));
            /*pag 610. send is similar to write. send(int sockfd, const void *buf, size_t nbytes, it flags)*/
            send(clfd, buf, strlen(buf),0);
        }
        else
        {
            /*get data from the pipe that reads created to exec /usr/bin/uptime */
            while(fgets(buf, BUFLEN, fp)!=NULL)
            {
                /* clfd is returned by accept and it is a socket descriptor
                connected to the client that called connect*/
                send(clfd, buf, strlen(buf), 0);
            }
            /*see popen pag. 542*/
            pclose(fp);
        }
        close(clfd);
    }
}


#include<stdio.h>
#include<stdlib.h>
#include<unistd.h> //_SC_HOST_NAME_MAX
#include<string.h>
#include<netdb.h> //Here are defined AF_INET and the others of the family
#include<syslog.h> //LOG_ERR
#include<errno.h> //errno
#include <sys/types.h>
#include <sys/wait.h>

#include"../common/utilities.h"
#include "error.h"

#define BUFLEN 128
#define QLEN 10
#define MAXADDRLEN 256
#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 156
#endif

int initserver(int type, const struct sockaddr *addr, socklen_t alen, int qlen);

void serveConnectionless(int sockfd);

int main(int argc, char* argv[])
{
    printf("entered main\n");
    struct addrinfo *ailist, *aip, hint;
    int sockfd, err, n;
    char *host;
    if (argc != 1)
    {
        printf("usage: ruptimed\n");
        exit(1);
    }
    if ((n = sysconf(_SC_HOST_NAME_MAX))<0)
    {
        n = HOST_NAME_MAX;
    }
    if((host = malloc(n)) == NULL)
    {
        printf("malloc error\n");
        exit(1);
    }
    if (gethostname(host, n)<0)
    {
        printf("gethostname error\n");
        exit(1);
    }
    printf("Daemonizing\n");
    daemonize("ruptimed");

    memset(&hint, 0, sizeof(hint)); //set to 0 all bytes
    /*If hints.ai_flags includes the AI_CANONNAME flag, then the ai_canon‐
       name field of the first of the addrinfo structures in the returned
       list is set to point to the official name of the host.*/
    //hint.ai_flags = AI_CANONNAME;
    hint.ai_flags |= AI_PASSIVE;
    hint.ai_socktype = SOCK_DGRAM;
    hint.ai_addr = NULL;
    hint.ai_next = NULL;

    if((err = getaddrinfo(NULL, "60185", &hint, &ailist))!=0)
    {
        printf("Error line 129 %d\n", err);
        syslog(LOG_ERR, "ruptimed: getaddrinfo error %s", gai_strerror(err));
        exit(1);
    }
    for (aip = ailist; aip!=NULL; aip = aip->ai_next)
    {
        if ((sockfd = initserver(SOCK_DGRAM, aip->ai_addr, aip->ai_addrlen, QLEN))>=0)
        {
            //printf("starting to serve\n");
            serveConnectionless(sockfd);
            printf("Exiting \n");
            exit(0);
        }
    }
    exit(1);
}


void serveConnectionless(int sockfd)
{
    int n;
    socklen_t alen;
    FILE *fp;
    char buf[BUFLEN];
    char abuf[MAXADDRLEN];
    struct sockaddr *addr = (struct sockaddr*)abuf;
    for(;;)
    {
        alen = MAXADDRLEN;
        if((n=recvfrom(sockfd, buf, BUFLEN, 0, addr, &alen))<0)
        {
            syslog(LOG_ERR, "ruptimed: recvfrom error %s", strerror(errno));
            exit(1);
        }
        if ((fp = popen("/home/usr/Desktop/openCV", "r")) == NULL)
        {
            /*sprintf copy the string passed as second parameter inside buf*/
            sprintf(buf, "error: %s\n", strerror(errno));
            /*pag 610. send is similar to write. send(int sockfd, const void *buf, size_t nbytes, it flags)*/
            //send(clfd, buf, strlen(buf),0);
            sendto(sockfd, buf, strlen(buf),0, addr, alen);
        }
        else
        {
            /*get data from the pipe that reads created to exec /usr/bin/uptime */
            if(fgets(buf, BUFLEN, fp)!=NULL)
            {
                sendto(sockfd, buf, strlen(buf),0, addr, alen);
            }
            /*see popen pag. 542*/
            pclose(fp);
        }
        //close(clfd);
    }
}


/*struct sockaddr *ai_addr;*/
/*socklen_t        ai_addrlen;*/
/*  initserver(SOCK_STREAM, aip->ai_addr,               aip->ai_addrlen, QLEN))>=0)*/
int initserver(int type,   const struct sockaddr *addr, socklen_t alen, int qlen)
{
    int fd, err;
    int reuse = 1;
    if ((fd = socket(addr->sa_family, type, 0))<0)
    {
        return (-1);
    }
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int))<0)
    {
        goto errout;
    }
    if(bind(fd, addr, alen)<0)
    {
        goto errout;
    }
    if (type == SOCK_STREAM || type == SOCK_SEQPACKET)
    {
        if(listen(fd, qlen)<0)
        {
            goto errout;
        }
    }
    return fd;
    errout:
        err = errno;
        close (fd);
        errno = err;
        return(-1);
}

文件错误。c

#include <netdb.h>
#include <stdlib.h>
#include<stdio.h>
#include <string.h>
#include<unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include "../common/error.h"
#include <signal.h>
#define BUFLEN  128
#define TIMEOUT 20
#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 156
#endif

//int connect_retry(int, int, int, const struct sockaddr *, socklen_t);

void print_uptime(int sockfd, struct addrinfo *aip);
void sigalrm(int signo);

int main(int argc, char *argv[])
{

    //char *host;
    struct addrinfo *ailist, *aip;
    struct addrinfo hint;
    int     sockfd, err;
    int n;
    struct sigaction sa;
    char *host;

    if (argc != 2)//not needed any more but keep it for consistency
        //err_quit("usage: ruptime hostname");
        printf("no argument passed but thats ok cuz im using 127.0.01 anyway\n");
    if ((n = sysconf(_SC_HOST_NAME_MAX))<0)
    {
        n = HOST_NAME_MAX;
    }

    if((host = malloc(n)) == NULL)
    {
        printf("malloc error\n");
        exit(1);
    }
    if (gethostname(host, n)<0)
    {
      printf("gethostname error\n");
      exit(1);
    }
    printf("hostname: %s\n", host);

    sa.sa_handler = sigalrm;
    sa.sa_flags = 0;
    sigemptyset(&sa.sa_mask);
    //third argument if not NULL would return the old handler
    if (sigaction(SIGALRM, &sa, NULL)<0)
    {
        err_sys("sigaction err");
    }
    memset(&hint, 0, sizeof(hint));
    hint.ai_socktype = SOCK_DGRAM;
    hint.ai_canonname = NULL;
    hint.ai_addr = NULL;
    hint.ai_next = NULL;
    //if ((err = getaddrinfo(argv[1], "60185", &hint, &ailist)) != 0)
    if ((err = getaddrinfo("127.0.0.1", "60185", &hint, &ailist)) != 0)
        err_quit("getaddrinfo error: %s", gai_strerror(err));
    for (aip = ailist; aip != NULL; aip = aip->ai_next)
    {
        printf("Trying a connection\n");
        /*if ((sockfd = connect_retry(aip->ai_family, SOCK_STREAM, 0,
        aip->ai_addr, aip->ai_addrlen)) < 0)*/
        if((sockfd = socket(aip->ai_family, SOCK_DGRAM,0))<0)
        {
            err = errno;
        }
        else
        {
            print_uptime(sockfd, aip);
            exit(0);
        }
    }
    fprintf(stderr, "can't contact \"127.0.0.1\": %s\n", strerror(err));
    err_exit(err, "can’t connect to %s", argv[1]);
}


void print_uptime(int sockfd, struct addrinfo *aip)
{
   int     n;
   char    buf[BUFLEN];
   buf[0] = 0;

   if (sendto(sockfd, buf, 1, 0, aip->ai_addr, aip->ai_addrlen)<0)
   {
       err_sys("sendto err");
   }
   //When the timer expires, SIGALRM is generated
   alarm(TIMEOUT);
   if ((n=recvfrom(sockfd, buf, BUFLEN, 0, NULL, NULL))<0)
   {
       if (errno !=EINTR)
       {
           alarm(0);
       }
       err_sys("recv error");
   }
   alarm(0);
   write(STDOUT_FILENO, buf, n);
}

void sigalrm(int signo)
{

}

utilities.c

#include <stdlib.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "constants.h"
#include "error.h"

/* for definition of errno */
/* ISO C variable aruments */
static void err_doit(int, int, const char *, va_list);
/*Nonfatal error related to a system call.
Print a message and return.*/
void err_ret (const char *fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    err_doit (1, errno, fmt, ap);
    va_end (ap);
}


/*Fatal error related to a system cal1.
* Print a message and terminate*/
void err_sys(const char *fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    err_doit (1, errno, fmt, ap);
    va_end (ap);
    exit(1);
}

/*Nonfatal error unrelated to a system call.
Error code passed as explict parameter
Print a message and return*/
void err_cont(int error, const char *fmt, ...)
{
    va_list ap;
    va_start (ap, fmt);
    err_doit(1, error, fmt, ap);
    va_end (ap);
}

/*Fatal error unrelated to a system call
t Error code passed as explict parameter
*Print a message and terminate.*/
void err_exit(int error, const char *fmt, ...)
{
    va_list ap;
    va_start(ap, fmt) ;
    err_doit (1, error, fmt, ap);
    va_end(ap);
    exit (1);
}

/*Fatal error related to a system call.
*Print a message, dump core, and terminate*/
void err_dump(const char *fmt, ...)
{
    va_list ap;
    va_start (ap, fmt);
    err_doit(1, errno, fmt, ap);
    va_end (ap);
    abort();/* dump core and terminate */
    exit (1);/* shouldn't get here */
}


/*Nonfatal error unrelated to a system call.


Print a message and return*/
void err_msg(const char *fmt,...)
{
    va_list ap;
    va_start (ap, fmt);
    err_doit (0, 0, fmt, ap);
    va_end (ap);
}

/* Fatal error unrelated to a system call.
* Print a message and terminate*/
void err_quit (const char *fmt, ...)
{
    va_list ap;
    va_start (ap, fmt);
    err_doit (0, 0, fmt, ap);
    va_end (ap);
    exit(1);
}

/*Print a message and return to caller.
*Caller specifies "errnoflag"*/
static void err_doit(int errnoflag, int error, const char *fmt, va_list ap)
{
    char buf [MAXLINE];
    vsnprintf (buf, MAXLINE-1, fmt, ap);
    if (errnoflag)
    {
        snprintf (buf+strlen(buf), MAXLINE-strlen(buf)-1, ": %s",
            strerror (error));
    }
    strcat(buf, "\n");
    fflush(stdout); /*in case stdout and stderr are the same*/
    fputs (buf, stderr);
    fflush(NULL); /* flushes all stdio output streams*/
}

0 个答案:

没有答案