将从客户端发送到服务器的数据保存到文件中具有无效字符

Saving data sent from client to server into a file has invalid characters

我正在尝试将包含字符串的文件从客户端发送到服务器,然后让服务器保存收到的结果。到目前为止,我已经设法将数据从客户端发送到服务器,但是当服务器将结果保存在文本文件中时,它包含无法读取的无效字符。

文件的内容有大约 10 行零,如下所示(并以红色突出显示),中间有随机字符:

POST /apikey=json&command={"Parameter" : "Value"}[=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=][=10=]ð|[=10=][=10=][=10=][=10=]|'^O[=10=][=10=]ÿÿÿÿ

我做了一些研究,并尝试使用二进制模式:(fp = fopen( "testfile.txt" , "wb" ); 但这并没有解决问题。

服务器

#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 <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>

#define PORT "3490"  // the port users will be connecting to

#define BACKLOG 10     // how many pending connections queue will hold

void sigchld_handler(int s)
{
    while(waitpid(-1, NULL, WNOHANG) > 0);
}

// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
    if (sa->sa_family == AF_INET) {
        return &(((struct sockaddr_in*)sa)->sin_addr);
    }

    return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

int main(void)
{
    int sockfd, new_fd;  // listen on sock_fd, new connection on new_fd
    struct addrinfo hints, *servinfo, *p;
    struct sockaddr_storage their_addr; // connector's address information
    socklen_t sin_size;
    struct sigaction sa;
    int yes=1;
    char s[INET6_ADDRSTRLEN];
    int rv;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE; // use my IP

    if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
        return 1;
    }

    // loop through all the results and bind to the first we can
    for(p = servinfo; p != NULL; p = p->ai_next) {
        if ((sockfd = socket(p->ai_family, p->ai_socktype,
                p->ai_protocol)) == -1) {
            perror("server: socket");
            continue;
        }

        if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
                sizeof(int)) == -1) {
            perror("setsockopt");
            exit(1);
        }

        if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
            close(sockfd);
            perror("server: bind");
            continue;
        }

        break;
    }

    if (p == NULL)  {
        fprintf(stderr, "server: failed to bind\n");
        return 2;
    }

    freeaddrinfo(servinfo); // all done with this structure

    if (listen(sockfd, BACKLOG) == -1) {
        perror("listen");
        exit(1);
    }

    sa.sa_handler = sigchld_handler; // reap all dead processes
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART;
    if (sigaction(SIGCHLD, &sa, NULL) == -1) {
        perror("sigaction");
        exit(1);
    }

    printf("server: waiting for connections...\n");

    while(1) {  // main accept() loop
        sin_size = sizeof their_addr;
        new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
        if (new_fd == -1) {
            perror("accept");
            continue;
        }

        inet_ntop(their_addr.ss_family,
            get_in_addr((struct sockaddr *)&their_addr),
            s, sizeof s);
        printf("server: got connection from %s\n", s);

{
        char buf[1000];
        ssize_t len;

        len = recv(new_fd, buf, sizeof(buf) - 1, 0);
        if (len > 0) {
                buf[len] = '[=11=]';
                printf("buffer: %s len: %d\n\n", buf, (int)len);

                        /* save to file */              
                    FILE *fp;
                    fp = fopen( "testfile.txt" , "wb" ); //b for binary
                    fwrite(buf, 1, sizeof buf, fp);
                    fclose(fp);

            }
    }



        if (!fork()) { // this is the child process
            close(sockfd); // child doesn't need the listener
            if (send(new_fd, "I received your message\n", 23, 0) == -1)
                perror("send");
            close(new_fd);
            exit(0);
        }
        close(new_fd);  // parent doesn't need this
    }

    return 0;
}

客户

#include <stdio.h> /* printf, sprintf */
#include <stdlib.h> /* read, write, close */
#include <string.h> /* memcpy, memset */
#include <sys/socket.h> /* socket, connect */
#include <netinet/in.h> /* struct sockaddr_in, struct sockaddr */
#include <netdb.h> /* struct hostent, gethostbyname */
#include <unistd.h>

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

int main(int argc,char *argv[])
{
    /* first what are we going to send and where are we going to send it? */
    int portno =        3490; /* 3490 or 8080 */
    char *host =        "192.168.1.65"; /* localhost: 127.0.0.1 or 192.168.1.65 */
    char *message_fmt = "POST /apikey=%s&command=%s HTTP/1.0\n\n";

    struct hostent *server;
    struct sockaddr_in serv_addr;
    int sockfd, bytes, sent, received, total;
    char message[1024],response[4096];

    //if (argc < 3) { puts("Parameters: <apikey> <command>"); exit(0); }

    /* fill in the parameters */
    sprintf(message,message_fmt,argv[1],argv[2]);
    printf("Request:\n%s\n",message);

    /* create the socket */
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) error("ERROR opening socket");

    /* lookup the ip address */
    server = gethostbyname(host);
    printf("ip address: %s\n\n", host);
    if (server == NULL) error("ERROR, no such host");

    /* fill in the structure */
    memset(&serv_addr,0,sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(portno);
    memcpy(&serv_addr.sin_addr.s_addr,server->h_addr,server->h_length);

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

    /* send the request */

/********************************* reading input data and converting into JSOn format ***********************/
   FILE *file = stdin;
    char a[50], b[50];
        while(1 == fscanf(file," %[^,]",a) ) /* Read data until a comma is detected, */
            {

               fgetc( file ); // Ignore , character

               fscanf(file," %[^,]",b); /* Read data until a comma is detected, */
               fgetc( file ); // Ignore , character

        printf("{\"%s\" : \"%s\"}\n",a,b); /* Display results into {"A":"B"} format */
    }


   ///sprintf(message,message_fmt,a[0],b[0]);


    //total = strlen(message);
//printf("sending message %d\n",total);
sprintf(a, message_fmt,"json","{\"Parameter\" : \"Value\"}\n");
//total = strlen(a); // this takes the value of 'a' eg: 1, 2, 3, 4, - 'a' will be 1,3 while b=2,4
total = strlen(message);
    sent = 0;
    do {
        bytes = write(sockfd,a+sent,total-sent);
        if (bytes < 0)
            error("ERROR writing message to socket");
        if (bytes == 0)
            break;
        sent+=bytes;
    } while (sent < total); //while (sent < 0);
    printf("Post request sent \n");

    //receive the response
    printf("Receiving response \n");
    memset(response,0,sizeof(response));
    total = sizeof(response)-1;
    received = 0;
    do {
        bytes = read(sockfd,response-received,total-received);
        if (bytes < 0)
            error("ERROR reading response from socket");
        if (bytes == 0)
            break;
        received+=bytes;
    } while(received < total); //while (received < 0);
    printf("Response received\n");

    if (received == total)
        error("ERROR storing complete response from socket");

    /* close the socket */
    close(sockfd);

    /* process response */
    printf("\nServer Response:\n%s\n\n",response);

    return 0;
}

总结
1- 从客户端向服务器发送字符串(例如 Hello World)
2- 服务器读取字符串,将其保存到文本文件中
3- 但文本文件包含无效字符和零

不要将 'sizeof buf' 字节写入文件 - 缓冲区可能没有完全填满数据。使用 recv() 调用返回的 'len' 值。