C语言 如何让我的服务器类注册来自我的客户端类的响应?

icomxhvb  于 2023-05-12  发布在  其他
关注(0)|答案(1)|浏览(130)

我已经尝试了所有方法,以便让我的服务器类在从客户端获得“CLOSE”消息时关闭套接字,或者在获得"AUTOTEST"消息时运行AutoTest(),等等。但每一次,它不注册消息,我不知道为什么。为了保持简短,我让AutoTest()函数只打印出一条消息,说它测试了它,因为主要的问题只是让消息注册。运行时的输出如下:

./PhotoLab_server: Preparing the server address...
./PhotoLab_server: Assigning the server name to the socket...
./PhotoLab_server: Listening on port 2004...
./PhotoLab_server: Accepted connection from client
./PhotoLab_server: Received message: AUTOTEST
./PhotoLab_server: Sending response: OK.
./PhotoLab_server: Received message: CLOSE
ST
./PhotoLab_server: Sending response: OK.

客户:

./PhotoLab_client: Using port 2004...
./PhotoLab_client: Creating a socket...
./PhotoLab_client: Preparing the server address...
./PhotoLab_client: Connecting to the server...
./PhotoLab_client: Sending a request AUTOTEST
./PhotoLab_client: Waiting for response...
./PhotoLab_client: Received response: OK.
./PhotoLab_client: Sending a request CLOSE
./PhotoLab_client: Waiting for response...
./PhotoLab_client: Received response: OK.
./PhotoLab_client: Sending a request
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>

/*** global definitions ***/
#define SLEN    80      /* maximum length of file names */
#define MAX_PIXEL 255   /* maximum pixel intesity value */

/* test all functions */
int AutoTest(void);

/* Displays an error message to the command line */
void FatalError(const char *Program, const char *ErrorMsg);

/* Prints out the available command flags */
void PrintUsage();

int main(int argc, char *argv[]) {
    int server_fd, new_socket;
    struct sockaddr_in address;
    int addrlen = sizeof(address);
    int port;

    /* Parse command line arguments */
    if (argc != 3 || strcmp(argv[1], "-p") != 0) {
        FatalError(argv[0], "Usage: %s -p <port>\n");
    }
    port = atoi(argv[2]);

    /* Validate the port number */
    if (port < 2000) {
        FatalError(argv[0], "Error: Port number must be greater than or equal to 2000\n");
    }

    printf("%s: Preparing the server address...\n", argv[0]);

    /* Create a socket */
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        FatalError(argv[0], "Error creating socket\n");
    }

    printf("%s: Assigning the server name to the socket...\n", argv[0]);

    /* Bind the socket to a specific IP address and port */
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(port);

    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
        FatalError(argv[0], "Error binding socket\n");
    }

    printf("%s: Listening on port %d...\n", argv[0], port);

    /* Listen for incoming connections */
    if (listen(server_fd, 3) < 0) {
        FatalError(argv[0], "Error listening on socket\n");
    }

    /* Accept incoming connections and serve client requests */
    while (1) {
    if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
        FatalError(argv[0], "Error accepting client connection\n");
    }

    printf("%s: Accepted connection from client\n", argv[0]);

    char buffer[256] = {0};
    int valread = 0; 
    while ((valread = read(new_socket, buffer, 256)) > 0) {
        printf("%s: Received message: %s", argv[0], buffer);

        /* Check if the client sent a CLOSE request */
        if (strcmp(buffer, "CLOSE") == 0) {
            break;
        }
        /* Check if the client sent an AUTOTEST request */
        else if (strcmp(buffer, "AUTOTEST") == 0) {
            AutoTest();
            const char *response = "Autotest completed";
            send(new_socket, response, strlen(response), 0);
        }
        /* Handle other client requests */
        else {
            /* Handle the client request */
            const char *response = "OK.";
            send(new_socket, response, strlen(response), 0);
            printf("%s: Sending response: %s\n", argv[0], response);
        }
    }

    /* Close the client connection */
    close(new_socket);
    printf("%s: Closed connection with client\n", argv[0]);

    /* Break out of the loop if a CLOSE request was received */
    if (valread == 0 || strcmp(buffer, "CLOSE") == 0) {
        printf("%s: Server exiting...\n", argv[0]);
        break;
    }
}
    /* Close the server socket */
    close(server_fd);
    printf("%s: Server socket closed\n", argv[0]);

    return 0;
}

/* test all functions */
int AutoTest(void) {
    printf("tested");
    return 1;
}

/* Displays an error message to the command line and exits the program */
void FatalError(const char *Program, const char *ErrorMsg) {
    fprintf(stderr, "%s: %s\n", Program, ErrorMsg);
    exit(EXIT_FAILURE);
}

/* Prints out the available command flags */
void PrintUsage() {
    printf("Usage:  PhotoLab_server -p <port_no>");
    printf("Options:");
    printf("-p                  Specify the server port number");
    printf("-h                  Display this usage information");
}

客户类别:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>

/* Displays an error message to the command line */
void FatalError(const char *Program, const char *ErrorMsg);

/* Sends a request to the specified socket */
int SendRequest(const int SocketFD, const char *ReqMsg);

/* Prints out the available command flags */
void PrintUsage();

int main(int argc, char *argv[]) {
    int x;
    char *server_ip;
    int port_number = -1;

    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        perror("./PhotoLab_client: Error creating a socket...");
        exit(1);
    }

    while (x < argc) {
        /* the server ip address option */
        if (strcmp(argv[x], "-ip") == 0) {
            if (x < argc - 1) {
                server_ip = argv[x+1];
            } else {
                printf("Missing argument for server IP address!\n");
                return 5;
            }
            x += 2;
            continue;
        }

        /* the port number option */
        if (strcmp(argv[x], "-p") == 0) {
            if (x < argc - 1) {
                if (sscanf(argv[x+1], "%d", &port_number) == 1) {
                    x += 2;
                    continue;
                } else {
                    printf("Invalid port number argument!\n");
                    return 5;
                }
            } else {
                printf("Missing argument for port number!\n");
                return 5;
            }
        }

        /* the help option */
        if (strcmp(argv[x], "-h") == 0) {
            PrintUsage();
            return 0;
        }

        /* the print option */
        if (strcmp(argv[x], "-print") == 0) {
            SendRequest(sockfd, "print");
            return 0;
        }

        /* the autotest option */
        if (strcmp(argv[x], "-autotest") == 0) {
            SendRequest(sockfd, "AUTOTEST");
            printf("autotest");
            return 0;
        }
        x++;
    }

    if (server_ip == NULL || port_number == -1) {
        printf("Missing required arguments!\n");
        return 5;
    }

    printf("%s: Using port %d...\n", argv[0], port_number);

    struct sockaddr_in serv_addr;
    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr(server_ip);
    serv_addr.sin_port = htons(port_number);

    printf("./PhotoLab_client: Creating a socket...\n");
    printf("%s: Preparing the server address...\n", argv[0]);

    if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
        perror("./PhotoLab_client: Error connecting to server...");
        exit(1);
    }

     printf("%s: Connecting to the server...\n", argv[0]);

    while (1) {
        char input[100];
        printf("%s: Sending a request ", argv[0]);
        fgets(input, sizeof(input), stdin);
        printf("%s: Waiting for response...\n", argv[0]);
        SendRequest(sockfd, input);

        char buffer[256] = {0};
        int valread = read(sockfd, buffer, 256);
        if (valread < 0) {
            FatalError(argv[0], "Error receiving response from server");
            exit(EXIT_FAILURE);
        }
        printf("%s: Received response: %s\n", argv[0], buffer);
        }

    return 0;
}

/* Displays an error message to the command line and exits the program */
void FatalError(const char *Program, const char *ErrorMsg) {
    fprintf(stderr, "%s: %s\n", Program, ErrorMsg);
    exit(EXIT_FAILURE);
}

/* Sends a request of what to do to the server */
int SendRequest(const int SocketFD, const char *ReqMsg) {
    int n = send(SocketFD, ReqMsg, strlen(ReqMsg), 0);
    if (n < 0) {
        FatalError("SendRequest", "Failed to send request message.");
    }
    return n;
}

/* Print the usage information */
void PrintUsage() {
    printf("-------------------------------------------------------------------------\n");
    printf("Usage: PhotoLab_client -ip <server_ip> -p <port_no> -print -autotest\n");
    printf("Options:\n");
    printf("-ip     Specify the server IP address\n");
    printf("-p      Specify the server port number\n");
    printf("-print          Send request to server to print supported DIP operations\n");
    printf("-autotest   Send request to server to run AutoTest functionality\n");
    printf("-h              Display this usage information\n");
    printf("-------------------------------------------------------------------------\n");
}

我试着做一个函数来接收消息,并多次更改服务器/客户端的代码,只是为了让它注册消息,但我不能弄清楚为什么它不起作用。

tv6aics1

tv6aics11#

你需要在每次迭代中将缓冲区清零。看看你得到了什么:

"AUTOTEST"  // this is the first message, then you get
"CLOSE_ST"  // ST left over from "AUTOTEST"

我把_放在那里,这样它就只是一个字符,你可以看到比较,但这实际上是'\n'或类似的东西,大概是从客户端发送的,所以strcmp"CLOSE"的比较失败,因为它实际上是在比较"CLOSE\nST"。也许这不是最有效的解决方案,但是您可以在每次迭代时将缓冲区清零,这样当消息从连接读入buffer时,您总是会得到NUL终止。就像

while ((valread = read(new_socket, buffer, 256)) > 0) {
   // do all you work, then clear the buffer
   // ... 
   memset(buffer, 0, sizeof(buffer));
}

会做到的
正如在注解中所讨论的,您还需要考虑fgets添加到sent命令中的换行符。您可以在客户端、服务器端消除它,或者在strcmp上考虑它。我的首选是在客户端using strcspan上消除它:

fgets(input, sizeof(input), stdin);
buffer[strcspn(buffer, "\n")] = 0; // writes 0 over the newline
printf("%s: Waiting for response...\n", argv[0]);
SendRequest(sockfd, input);

相关问题