使用UDP传输数据时出现问题

问题描述 投票:0回答:1

我为客户端和服务器编写了一个程序,它会向服务器发送一条命令,在服务器上执行用户提到的次数,并每次传输发送 64 字节的内容,直到所有数据发送到客户端并打印。问题是它没有按照我的预期工作,我检查了错误,但无法解决问题。请帮助我,我将附上客户端和服务器程序。

客户:

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

typedef struct sockaddr_in sock;
typedef struct sockaddr sck;

int main()
{
    char cmd[10],rcv[65];
    int tm,end,ack = 1;

    printf("Enter any standard LS command: ");
    scanf("%s",cmd);
    printf("Enter no.of times to be executed: ");
    scanf("%d",&tm);

    int sockfd = socket(AF_INET,SOCK_DGRAM,0);
    sock addr;
    int len = sizeof(addr);

    addr.sin_family = AF_INET;
    addr.sin_port = htons(5000);
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");

    sendto(sockfd,cmd,sizeof(cmd),0,(sck *)&addr,len);
    sendto(sockfd,&tm,sizeof(int),0,(sck *)&addr,len);

    while(end)
    {
        int sz = recvfrom(sockfd,rcv,sizeof(rcv),0,(sck *)&addr,&len);
        printf("%s\n",rcv);

        if(sz == 64)
            sendto(sockfd,&ack,sizeof(int),0,(sck *)&addr,len);
        else
        {
            ack = 0;
            sendto(sockfd,&ack,sizeof(int),0,(sck *)&addr,len);
        }

        recvfrom(sockfd,&end,sizeof(int),0,(sck *)&addr,&len);
    }

    close(sockfd);
}

服务器:

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

typedef struct sockaddr_in sock;
typedef struct sockaddr sck;

int main()
{
    char cmd[10],snd[65],ch;
    int tm,cn = 0,end = 1, ack;

    int sockfd = socket(AF_INET,SOCK_DGRAM,0);
    sock addr;
    int len = sizeof(addr);

    addr.sin_family = AF_INET;
    addr.sin_port = htons(5000);
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");

    bind(sockfd,(sck *)&addr,sizeof(addr));

    recvfrom(sockfd,cmd,sizeof(cmd),0,(sck *)&addr,&len);
    recvfrom(sockfd,&tm,sizeof(int),0,(sck *)&addr,&len);

    int fd = open("op.txt",O_CREAT | O_WRONLY | O_TRUNC,0644);
    int bc = dup(1);
    dup2(fd,1);

    for(int i = 1;i <= tm;i++)
        system(cmd);

    close(fd);
    dup2(bc,1);

    fd = open("op.txt",O_RDONLY);

    while(read(fd,&ch,1))
    {
        if(cn < 64)
            snd[cn] = ch;
        else
        {
            snd[cn] = '\0';
            sendto(sockfd,snd,sizeof(snd),0,(sck *)&addr,len);
            recvfrom(sockfd,&ack,sizeof(ack),0,(sck *)&addr,&len);
            if(!ack)
            {
                end = 0;
                sendto(sockfd,&end,sizeof(int),0,(sck *)&addr,len);
                break;
            }
            else
                sendto(sockfd,&end,sizeof(int),0,(sck *)&addr,len);
            cn = 0;
        }
        cn++;
    }

    close(fd);
    close(sockfd);
}
c linux network-programming udp
1个回答
0
投票

我谨慎地假设你问题的初衷是这样的

  • 客户
    • 客户端发送一些系统命令,例如
      ls -al .
      和重复计数(服务器执行客户端给定命令的次数),例如
      3
    • 服务器重复执行命令后,也会将输出显示在客户端的显示屏上。
  • 服务器
    • 接收来自客户端的命令和重复计数。 (例如,
      ls -al .
      3
    • 执行命令指定的次数。
    • 将组合输出存储到
      op.txt
      (至少你的代码似乎可以使用此文件)。
    • 再次将
      op.txt
      的内容发送回客户端。

基于这个假设,我又重写了程序。

// server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <fcntl.h>

#define SERVER_PORT 5000
#define BUFFER_SIZE 1024
#define OUTPUT_FILE "op.txt"
#define END_MESSAGE "END"

// Function to send data to the client
void send_data(int sockfd, struct sockaddr_in *client_addr, socklen_t addr_len, const char *data, size_t data_len) {
    ssize_t sent_bytes = sendto(sockfd, data, data_len, 0, (struct sockaddr *)client_addr, addr_len);
    if (sent_bytes == -1) {
        perror("sendto failed");
    }
}

int main() {
    int sockfd;
    struct sockaddr_in server_addr, client_addr;
    socklen_t addr_len = sizeof(client_addr);
    char buffer[BUFFER_SIZE];
    char command[256];
    int repetition;

    // Create UDP socket
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    // Bind the socket to server address
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    server_addr.sin_addr.s_addr = INADDR_ANY; // Listen on all interfaces

    if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        perror("bind failed");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    printf("Server is up and listening on port %d...\n", SERVER_PORT);

    // Receive command from client
    ssize_t bytes_received = recvfrom(sockfd, buffer, BUFFER_SIZE - 1, 0, (struct sockaddr *)&client_addr, &addr_len);
    if (bytes_received == -1) {
        perror("recvfrom failed for command");
        close(sockfd);
        exit(EXIT_FAILURE);
    }
    buffer[bytes_received] = '\0';
    strncpy(command, buffer, sizeof(command) - 1);
    command[sizeof(command) - 1] = '\0'; // Ensure null-termination
    printf("Received command: %s\n", command);

    // Receive repetition count from client
    bytes_received = recvfrom(sockfd, &repetition, sizeof(repetition), 0, (struct sockaddr *)&client_addr, &addr_len);
    if (bytes_received == -1) {
        perror("recvfrom failed for repetition count");
        close(sockfd);
        exit(EXIT_FAILURE);
    }
    printf("Repetition count: %d\n", repetition);

    // Execute the command the specified number of times and capture the output
    FILE *fp = fopen(OUTPUT_FILE, "w");
    if (fp == NULL) {
        perror("Failed to open output file");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    // Redirect stdout to the file
    int stdout_copy = dup(STDOUT_FILENO);
    if (stdout_copy == -1) {
        perror("dup failed");
        fclose(fp);
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    if (dup2(fileno(fp), STDOUT_FILENO) == -1) {
        perror("dup2 failed");
        fclose(fp);
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    // Execute the command multiple times
    for (int i = 0; i < repetition; i++) {
        printf("Execution %d:\n", i + 1);
        if (system(command) == -1) {
            fprintf(stderr, "Failed to execute command: %s\n", command);
        }
        printf("\n"); // Add spacing between executions
    }

    // Restore stdout
    if (dup2(stdout_copy, STDOUT_FILENO) == -1) {
        perror("dup2 restore failed");
    }
    close(stdout_copy);
    fclose(fp);

    // Open the output file for reading
    fp = fopen(OUTPUT_FILE, "r");
    if (fp == NULL) {
        perror("Failed to open output file for reading");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    printf("Sending output to client...\n");

    // Send the file content in chunks
    while (fgets(buffer, sizeof(buffer), fp) != NULL) {
        send_data(sockfd, &client_addr, addr_len, buffer, strlen(buffer));
        usleep(10000);
    }

    // Send the END message to indicate completion
    send_data(sockfd, &client_addr, addr_len, END_MESSAGE, strlen(END_MESSAGE) + 1);

    printf("Output sent successfully.\n");

    fclose(fp);
    close(sockfd);
    return 0;
}
// client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define SERVER_PORT 5000
#define SERVER_IP "127.0.0.1"
#define BUFFER_SIZE 1024
#define END_MESSAGE "END"

// Function to send data to the server
void send_data(int sockfd, struct sockaddr_in *server_addr, socklen_t addr_len, const char *data, size_t data_len) {
    ssize_t sent_bytes = sendto(sockfd, data, data_len, 0, (struct sockaddr *)server_addr, addr_len);
    if (sent_bytes == -1) {
        perror("sendto failed");
        exit(EXIT_FAILURE);
    }
}

// Function to receive data from the server
ssize_t receive_data(int sockfd, char *buffer, size_t buffer_size, struct sockaddr_in *server_addr, socklen_t *addr_len) {
    ssize_t received_bytes = recvfrom(sockfd, buffer, buffer_size - 1, 0, (struct sockaddr *)server_addr, addr_len);
    if (received_bytes == -1) {
        perror("recvfrom failed");
        exit(EXIT_FAILURE);
    }
    buffer[received_bytes] = '\0'; // Null-terminate the received data
    return received_bytes;
}

int main() {
    char command[256];
    int repetition;
    char buffer[BUFFER_SIZE];
    struct sockaddr_in server_addr;
    socklen_t addr_len = sizeof(server_addr);

    // Get user input
    printf("Enter the command to execute (e.g., ls -al .): ");
    fgets(command, sizeof(command), stdin);
    command[strcspn(command, "\n")] = '\0'; // Remove newline character

    printf("Enter the number of times to execute the command: ");
    if (scanf("%d", &repetition) != 1 || repetition < 1) {
        fprintf(stderr, "Invalid repetition count.\n");
        exit(EXIT_FAILURE);
    }

    // Create UDP socket
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    // Configure server address
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    if(inet_aton(SERVER_IP, &server_addr.sin_addr) == 0){
        fprintf(stderr, "Invalid server IP address.\n");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    // Send command length and command
    send_data(sockfd, &server_addr, addr_len, command, strlen(command) + 1);

    // Send repetition count
    send_data(sockfd, &server_addr, addr_len, (char *)&repetition, sizeof(repetition));

    printf("\n--- Receiving Output ---\n");

    // Receive data until "END" message is received
    while (1) {
        ssize_t bytes_received = receive_data(sockfd, buffer, BUFFER_SIZE, &server_addr, &addr_len);
        if (strcmp(buffer, END_MESSAGE) == 0) {
            printf("\n--- End of Output ---\n");
            break;
        }
        printf("%s", buffer);
    }

    close(sockfd);
    return 0;
}

执行示例如下

server.c execution client.c execution

我希望这就是你当时想要的......

© www.soinside.com 2019 - 2024. All rights reserved.