1

我正在编写一个像下载服务器一样的客户端服务器。客户端向服务器请求一个文件名,然后服务器搜索该文件是否存在。它工作正常,但我观察到一些奇怪的事情:当客户端下载从服务器请求的文件时,下载文件的大小与原始文件的大小不同。

这是服务器代码:

//  Server.c

#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdarg.h>     /* ANSI C header file */
#include <syslog.h>     /* for syslog() */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>

/* Following shortens all the typecasts of pointer arguments: */
#define SA      struct sockaddr
#define ListenQ 5
#define MAXLINE 1024    /* max text line length */

void error(char *msg);

/* to define mode for read() or write() */
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | S_IRGRP | S_IWGRP;
volatile sig_atomic_t eflag = 0;

int listenfd, connfd;   /* to define Server file descriptor */
int sockfd, fd;         /* to define Client file descriptor */
socklen_t clilen;
struct sockaddr_in servaddr;

char buffer[MAXLINE + 1];/* define buffer to send and recive with */
char _fileName[128];

int n;                  /*  to count from reading or wrinting in sockets */
int portno, stringlen;
int CmpValue, i;
int fd_Cli;
int daemon_proc;        /* set nonzero by daemon_init() */
uint8_t state;          /* define 1 byte state for  existance files in sever */
uint8_t secret;
//char fileName[128];
//char *fileTocmp="abc.txt";

int main(int argc, char **argv)
{
    /*Error checking for providing  appropirate port# */
    if (argc < 2)
        error("Error,no port provided, please enter the port#:22011 \n");

    /*open listening socket for server      note the Socket not socket */
    listenfd = socket(AF_INET, SOCK_STREAM, 0);

    /*
     * to convert the port# from ascii to int to deal with it as int in
     * address structure
     */
    portno = atoi(argv[1]);

    //if(portno!=22011)
    //error(" please enter the port#:22011\n");

    // to zero the structre adress
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(portno);

    // to bind the adresses to server
    bind(listenfd, (SA *) & servaddr, sizeof(servaddr));

    //to put the open socekt descrptor
    //to put the open socekt descrptor
    listen(listenfd, ListenQ);

    puts("Waiting for incoming connections...\n");




    for (;;) {
        clilen = sizeof(servaddr);

        /*
         * To handle Interupt which leads Accept() to interupt so here
         * to restart Accept()
         */
        if ((connfd = accept(listenfd, (SA *) & servaddr, &clilen)) < 0) {
            if (errno == EINTR)
                continue;       /* back to for() */
            else
                error("accept error");
        }


        //bzero(&buffer,sizeof(buffer));
        //n=read(connfd,&buffer,sizeof(buffer));
        secret = 0x55;
        sprintf(buffer, "%d", secret);
        n = write(connfd, &buffer, sizeof(buffer));
        printf("Sending Byte 0x55: (%x) to client (%s:%d) .\n", secret,
               inet_ntoa(servaddr.sin_addr), ntohs(servaddr.sin_port));
        bzero(&buffer, sizeof(buffer));
        n = read(connfd, &buffer, sizeof(buffer));

        printf("recived 0XAA is :%s from the client\n", buffer);

        ///////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////
        //this function to read and write from and to client

        printf("(%s:%d) connected.\n", inet_ntoa(servaddr.sin_addr),
               ntohs(servaddr.sin_port));
        printf("waiting to provide file name From: (%s:%d) \n\n",
               inet_ntoa(servaddr.sin_addr), ntohs(servaddr.sin_port));

        /*  to copy the file name to var fileName */
        //strncpy(fileName,fileTocmp,128);


        for (;;) {
            //bzero(&buffer,sizeof(buffer));
            //n=read(connfd,&buffer,sizeof(buffer));

            /////////////////////////////////////////////

            bzero(&buffer, sizeof(buffer));
            n = read(connfd, &buffer, sizeof(buffer));
            printf("Recived file name :%s from client: (%s:%d)\n", buffer,
                   inet_ntoa(servaddr.sin_addr), ntohs(servaddr.sin_port));
            //printf("\n");
            /*
             ///////////////////////////////////////////
             * Hehow to check if file exists in cre is the core of
             * comparing files at server if exists or not.
             ///////////////////////////////////////////
             */

            /*
             * compare the filename provided by User with the file exist
             * in server
             */
            //
            char *p;
            if ((p = strchr(buffer, '\n')))
                *p = 0;
            //CmpValue=access (buffer, F_OK|R_OK| W_OK);
            printf("the buffer now is : %s\n", buffer);
            /////////////////////////////
            strncpy(_fileName, buffer, 128);
            CmpValue = access(buffer, F_OK | R_OK);
            printf("the value of CMPaccess is : %d\n", CmpValue);

            if (CmpValue == 0) {
                bzero(&buffer, sizeof(buffer));
                state = 1;
                /* to print the state=1 to buffer */
                sprintf(buffer, "%d", state);
                /* to print the state=1 to stdout */
                printf("Sending (%d) to the client : (%s:%d)\n", state,
                       inet_ntoa(servaddr.sin_addr),
                       ntohs(servaddr.sin_port));
                printf("\n");
                /* to send the state=1 to client */
                n = write(connfd, &buffer, sizeof(buffer));
                ///////////////////////////////////////////
                printf("here is buffer before Func open is : %s\n",
                       buffer);

                fd = open(_fileName, O_RDONLY);
                /* To Handle the file descriptor error. */
                if (fd < 0) {
                    bzero(&buffer, sizeof(buffer));
                    printf
                        ("Sending Error value : %s (to client@ %s:%d) \n",
                         strerror(errno), inet_ntoa(servaddr.sin_addr),
                         ntohs(servaddr.sin_port));

                    /* to print the ERROR to buffer */
                    snprintf(buffer, sizeof(buffer), "ERROR(%d):%s", errno,
                             strerror(errno));
                    /* to send the ERROR to client */
                    n = write(connfd, &buffer, sizeof(buffer));
                    if (n < 0) {
                        error("Error,Writing to socket \n");
                    }
                    continue;
                }

                int serverRead;
                while ((serverRead = read(fd, buffer, MAXLINE + 1) > 0)) {
                    /* to read from open file descriptor */
                    n = write(connfd, &buffer, n);
                    printf("------- the value of serverRead is : %d\n",
                           serverRead);
                    if (n < 0) {
                        error("Error,Reading from socket \n");
                    }
                }

                printf("hon ya 3rs 5lset writing ............\n");
                close(connfd);
                //printf("buffer now is : %s\n",buffer);
                //buffer[n] = '\0';
                //close(connfd);
                /*
                 * to send the buffer contents which "is from reading
                 * file descripotr" to client
                 */
            } else {
                bzero(&buffer, sizeof(buffer));
                state = 0;
                /* to print the state=0 to stdout */
                printf("Sending (%d) to the client : (%s:%d)\n", state,
                       inet_ntoa(servaddr.sin_addr),
                       ntohs(servaddr.sin_port));
                printf("\n");
                /* to print the state=0 to buffer */
                sprintf(buffer, "%d", state);
                n = write(connfd, &buffer, sizeof(buffer));
                if (n < 0) {
                    error("Error,Writing to socket \n");
                }
                /* to send the state=0 to client */
            }

        } // end of for

        ///////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////
        //this function to read and write from and to client


        //close(connfd);
    }
    //return 0;
}



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

所以我还没有找到解决办法。也许它与Unix 系统调用中的openand实现有关?read

4

1 回答 1

1

从文件中读取一些字节数后,这应该是您写入的字节数。对我来说,您似乎正在编写一些与读取的数字完全无关的字节数:

            int serverRead;
            while ((serverRead = read(fd, buffer, MAXLINE + 1) > 0)) {
                /* to read from open file descriptor */
                n = write(connfd, &buffer, n);
                printf("------- the value of serverRead is : %d\n",
                       serverRead);
                if (n < 0) {
                    error("Error,Reading from socket \n");
                }
            }

相反,您应该更改调用方式write()serverReadbuffer. write()意识到写入可能比请求的数量短,因此您需要通过围绕调用本身的循环来防止这种情况。

    ssize_t bytes_written = 0;
    while (bytes_written < serverRead) {
        n = write(connfd, buffer + bytes_written, serverRead - bytes_written);
        if (n > 0) {
            bytes_written += n;
            continue;
        }
        //...handle error
    }
于 2013-10-24T19:24:53.323 回答