客户端与服务器通信,执行命令

标签 c fork exec

我正在尝试基于套接字通信进行命令行。我唯一的问题是执行 exexvp 后(并且数据正在客户端上打印),客户端关闭,我想让他保持事件状态。

这是我的代码:

客户端.c

#include <unistd.h> 
#include <stdio.h> 
#include <sys/socket.h> 
#include <stdlib.h> 
#include <netinet/in.h> 
#include <string.h> 
#include <sys/types.h>
#include <netdb.h>
#define PORT_NUMBER 1754
#define HOST_NUMBER

void error(const char *msg) 
{ 
    perror(msg); 
    exit(0); 
}

int main(int argc, char *argv[]) 
{ 
    int sockfd, port_number, n;     
    struct sockaddr_in serv_addr; 
    struct hostent *server;

    char buffer[256];

    if (argc < 3) { 
        //fprintf(stderr, "usage %s hostname port\n", argv[0]); 
        //first parameter is ip address
        printf("usage %s hostname port\n", argv[0]);        
        exit(0); 
    } 
    port_number = atoi(argv[2]);                        

    sockfd = socket(AF_INET, SOCK_STREAM, 0); 

    if (sockfd < 0 ) 
        error("ERROR opening socket!Socket failed!"); 

    printf("Trying to connect...\n");
    server = gethostbyname(argv[1]);  //ip address

    if (server == NULL) { 
        error( "ERROR, no such host"); 
        //fprintf(stderr, "ERROR, no such host\n");  exit(0); 
    } 
    bzero((char *) &serv_addr, sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;  //AF_UNIX

    bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);

    serv_addr.sin_port = htons(port_number); 

    if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) 
        error("ERROR connecting"); 

    printf("Connected!\n");
    printf("%s_>\n",argv[1]);

    while(1) {
        printf("Please enter the message: "); //THE CLIENT MUST WRITE A COMMAND

        fgets(buffer, 256, stdin);     //apo stdin sto buffer
        n = write(sockfd, buffer, strlen(buffer)); //apo buffer sto socket

        if(n < 0 ) {
            error("ERROR writing to socket");
        }
        bzero(buffer, 256);

        if ( recv(sockfd, buffer, 256, 0) < 0) {
            printf("Server closed connection\n");
        }
        printf("%s\n", buffer);
    }
    return 0;
}

服务器.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/wait.h>
#include <errno.h>

void parse(char *vector_args[20], char *buffer){
    buffer[strcspn(buffer, "\n")] =0;

    int i=0;
    char * pch;

    pch = strtok (buffer," "); 

    while (pch != NULL )
    {
        vector_args[i]=pch;                
        printf (" %s\n",pch);
        pch = strtok (NULL, " ");          
        i++;
    }

    vector_args[i]=NULL;                             
    int k=0;
    for(k=0; k<=i; k++) {
        printf("vector %d = %s \n",k,vector_args[k]);
    }
}

int main(int argc, char *argv[])
{
    int sockfd, newsockfd, portno;
    socklen_t clilen;
    char buffer[256];
    struct sockaddr_in serv_addr, cli_addr;
    int n;
    char str[INET_ADDRSTRLEN];

    char *vector_args[20];

    int status;
    char *fd[2];
    if (argc < 2)
    {
        fprintf(stderr, "No port provided\n");
        exit(1);
    }
    unlink("sockfd");    //remove any old socket
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
        error("ERROR opening socket");
    bzero((char *) &serv_addr, sizeof(serv_addr));
    portno = atoi(argv[1]);
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(portno);
    if (bind(sockfd,(struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
        error("ERROR on binding");
    int l = listen(sockfd, 5);
    if (l < 0) 
    { 
            error("listen failed!"); 

    }
    clilen = sizeof(cli_addr);
    printf( "Server waiting for a connection...\n " );
    while(1) {
        newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
        if (newsockfd < 0)
            error("ERROR on accept");

        if (inet_ntop(AF_INET, &cli_addr.sin_addr, str, INET_ADDRSTRLEN) == NULL) {
            fprintf(stderr, "Could not convert byte to address\n");
            exit(1);
        }

        fprintf(stdout, "Connected!\nThe client address is :%s\n", str);

        //fork new process
        int pid = fork();

        if (pid == -1 ) {
            error("ERROR in new process creation");
            close(newsockfd);
            continue;
        }else if( pid != 0){
            //parent process
            close(newsockfd);//h edw h prin to continue
            printf( " I am parent process %d\n " ,getpid());     //BGALE
            if (wait(&status)== -1) /* Wait for child*/
            {
                perror( " wait " );
            }
            check_child_exit(status);
            continue;
         }else if (pid == 0) {
              //child process
            close(sockfd);

            bzero(buffer, 256);
            while(1) {
                n = read(newsockfd, buffer, 255); //apo socket ston buffer 
                if (n < 0 )
                    error("ERROR reading from socket");

                printf("Here is the message: %s\n", buffer);
                n = write(newsockfd, "I got your message", 18);
                bzero(buffer, 256);
                close(1);                //close stdin
                dup2( newsockfd, 1); 
                close(0);                //close stdout
                dup2( newsockfd, 0);     

                parse(vector_args,buffer);

                execvp(vector_args[0] , vector_args );          

                perror( " execvp " );
                exit(EXIT_FAILURE);

                bzero(buffer, 256);
            }
            close(newsockfd);
            break;
       }   
    }
}

您知道如何更改代码才能正常工作吗?

最佳答案

循环

    while (1) {
        ....
        execvp(....);
    }

有效执行一次。原因是成功的 execvp 用任何 vector_args 请求替换代码,并且执行的进程在完成后退出。

如果我正确理解你的目标(每个连接一个进程,在循环中执行外部命令),你还需要一个分支,沿着

    while (1) {
        ....
        if ((pid = fork()) == 0) {
            execvp(....);
        } else if (pid > 0) {
            waitpid(....);
        } else {
            handle_error();
        }
    }

关于客户端与服务器通信,执行命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54425740/

相关文章:

c - 如何正确发送 time_t 指针到函数?尝试这样做时遇到 valgrind 错误

c - 从文件 (CSV) c 中高效读取和复制数据/字符串

c++ - 如何在 Visual Studio 中忽略 DLL 中的断点

php - 如何使用php在根目录上方创建文件夹

c - 无法正确排序二维字符数组

php - 随后的 pcntl_signal 信号不会启动处理程序

fork - 在xv6中,如何让子进程在fork()之后首先运行?

linux - 使 ExecStartPost 命令在后台运行

C 编程 - execlp() 有帮助吗?

连续两次执行 os/exec Command.Start()