1

基本上我会在一段时间内使用 recv 来读取从我的客户端发送的数据。客户端完成读取文件并发送它,但服务器仍在此期间。我如何通知服务器文件发送完成意味着客户端的feof?

服务器

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>      /*For Sockets*/
#include <sys/socket.h>     /*For Sockets*/
#include <netdb.h>      /*For gethostbyaddr()*/
#include <netinet/in.h>     /*For internet sockets*/
#include <dirent.h>


/*Function for creating the lof file of Server*/

void log_event (char *message,char *filename)
{

FILE *file; 
char *log_this;

time_t system_time; //Get the system time
time(&system_time);

log_this=strcat(ctime(&system_time),message); //Create the message to log 

/*Check for filename and log as appropiate*/

if (filename!=NULL)
    {
        file = fopen(filename,"a+"); 
        fprintf(file,"%s",log_this); /*writes the message*/
        fclose(file); /*done!*/     
    }
else    
    {
        file = fopen("ftp_tracelog.txt","a+"); 
        fprintf(file,"%s",log_this); /*writes the message*/
        fclose(file); /*done!*/ 
    }

}

int main (int argc,char *argv[])
{

/*DECLERATIONS*/

char *filename; 
char message [1024];
char *temp;
char temp_2[1024];
char buf[1024];
char *p=buf;
ssize_t  bytesRemaining = 1024;
ssize_t  bytesRemaining2 = 50;
char request[50];
char command[5];
char c[50];
char copy[1024]="COPY_OF_";
FILE *fp;
DIR *dp;
char list[1024];
int port,sock,newsock,serverlen,clientlen,fname_len,recvMsgSize,i,len,count;


struct sockaddr_in server,client;
struct sockaddr *serverptr, *clientptr;
struct hostent *rem;
struct dirent *ep;     

/*END OF DECLERATIONS*/

/*Check for required arguments and get them as appropiate*/

if (argc < 2) { 
        /* Check if server's port number is given */
        printf("Please give the port number!!!\n");
        exit(1);
        }

/*if server's port number is given and filename for log is given*/

if(argc>2){
    filename=argv[1];
    port=atoi(argv[2]);
       }

/*If only port is given*/
if (argc==2){
    port=atoi(argv[1]);
    filename=NULL;
         }

temp="--Server is Starting!!--";
sprintf(message,"%s\n",temp);
log_event(message,filename);

/* Create socket */

if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0)
{perror("socket"); exit(1); }

server.sin_family = PF_INET; /* Internet domain */
server.sin_addr.s_addr = htonl(INADDR_ANY); /* My Internet address */
server.sin_port = htons(port); /* The given port */
serverptr = (struct sockaddr *) &server;
serverlen = sizeof (server);

/* Bind socket to address */

if (bind(sock, serverptr, serverlen) < 0) {
perror("bind"); exit(1); }

/* Listen for connections */

if (listen(sock, 40) < 0) { /* 5 max. requests in queue */
perror("listen"); exit(1); }

temp="---Listening for connections to port";
sprintf(temp_2,"%d----",port);
sprintf(message,"%s:%s\n",temp,temp_2);
log_event(message,filename);

/*Accepting Connecttion*/

while(1) {
    clientptr = (struct sockaddr *) &client;
    clientlen = sizeof(client);

        /* Accept connection */
        if ((newsock = accept(sock, clientptr, &clientlen)) < 0){ 
        perror("accept"); exit(1);}

        /* Find client's address */
        if ((rem = gethostbyaddr((char *) &client.sin_addr.s_addr,
        sizeof (client.sin_addr.s_addr), client.sin_family)) == NULL) {
        perror("gethostbyaddr"); exit(1);}


temp="----Accepted connection from ";
sprintf(temp_2,"%s----", rem -> h_name);
sprintf(message,"%s:%s\n",temp,temp_2);
log_event(message,filename);

/* Create child for serving the client */
switch (fork()) {

case -1:
perror("fork"); exit(1);

case 0: /* Child process */



do{

    /* Receive message from client */
    if ((recvMsgSize = recv(newsock,request,sizeof(request),0))< 0)
    perror("recv() failed");



printf("%s\n",request);
//printf("%s\n",command);

/*IF YOU ARE GOING TO EXECUTE AN LS COMMAND*/

if (strcmp(request,"ls")==0)
    {
        dp = opendir ("./");

        if (dp != NULL)
          { /*LOG LS REQUEST*/

            temp="--Client ";
            sprintf(temp_2,"%s requested ls -------",rem -> h_name);
            sprintf(message,"%s:%s\n",temp,temp_2);
            log_event(message,filename);

            /*SEND ALL DIRECTORY LISTING*/    

            while (ep = readdir (dp))
            {
                strcpy(list,ep->d_name);
                //printf("sending:%s\n",list);
                if (send(newsock,list,sizeof(list), 0)!= sizeof(list))
                perror("send() sent a different number of bytes than expected");
            }
            //IF DIRECORY IS FINISHED SEND A LAST MESSAGE FOR ENDING

                (void) closedir (dp);
            if (send(newsock,"end",sizeof("end"), 0)!= sizeof("end"))
            perror("send() sent a different number of bytes than expected");    
        }       

        else
        perror ("Couldn't open the directory");

    }

/*IF THE COMMAND IS PUT*/

if (strcmp(request,"put")==0) 
    {
    sprintf(buf,"");
    printf("execute put!!\n");
        do{
            ssize_t recvd;
            while (bytesRemaining) {

                if (( recvd =recv(newsock,p,bytesRemaining,0))< 0){
                perror("recv() failed");}
                bytesRemaining -= recvd;     // keep track of bytes left
                p += recvd;             
                    }
          }while (buf=="");
    strcat(copy,buf);

    fp=fopen(copy,"w+");
    count=0;

    while (c!="")
    {
        bzero(c,sizeof(c));
        if ((recvMsgSize = recv(newsock,c,sizeof(c),0))< 0)
        perror("recv() failed");
        fprintf(fp,"%s",c);

    }
    fclose(fp);
    printf("!!DONE!!!!\n");
    //printf("%s",request);

    }

}while (strcmp(request,"end")!=0); //run until client sents end request

/*LOG EXIT OF CLIENT*/

temp="--Client";
    sprintf(temp_2,"%s is disconnected---",rem -> h_name);
    sprintf(message,"%s:%s\n",temp,temp_2);
    log_event(message,filename);

close(newsock); /* Close socket */
exit(0);
} /* end of switch */
}/*end of while*/
}

客户

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>

int main (int argc,char *argv[])
{

int port, sock, serverlen,recvMsgSize,was_read;
int fname_len,msg_len,request_len;
char buf[256];
char *fname;
char request[50];
char list[1024];
char msg[512];
char op[1000];
char temp[5];
char *temp3;
char read;
FILE *fp;
char b[50];

struct sockaddr_in server;
struct sockaddr *serverptr;
struct hostent *rem;

temp3="put";

/* Are server's host name and port number given? */
if (argc < 3) {
printf("Please give host name and port number\n"); exit(1);

}

/* Create socket */
if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
exit(1);
}

/* Find server address */
if ((rem = gethostbyname(argv[1])) == NULL) {
herror("gethostbyname"); exit(1);
}

/* Convert port number to integer */
port = atoi(argv[2]);

/* Internet domain */
server.sin_family = PF_INET; 
bcopy((char *) rem -> h_addr, (char *) &server.sin_addr,
rem -> h_length);

/*Server's Internet address and port*/
server.sin_port = htons(port); 
serverptr = (struct sockaddr *) &server;
serverlen = sizeof(server);


if (connect(sock, serverptr, serverlen) < 0) { /* Request connection */
perror("connect"); 
exit(1); }

printf("Requested connection to host %s port %d\n", argv[1], port);



do{

printf("Please enter request\n:");
scanf("%s",request);

/* Send the string to the server */
if (send(sock,request,sizeof(request), 0)!= sizeof(request))
perror("send() sent a different number of bytes than expected");

if(strcmp(request,"ls")==0)
{
    sprintf(list,"");

    /*Recieve from server*/
    while(strcmp(list,"end")!=0){

        if ((recvMsgSize = recv(sock,list,sizeof(list),0))< 0)
        perror("recv() failed");

        if(strcmp(list,"end")!=0){
        printf("%s\n",list);
                    }
                    }
bzero(request,sizeof(request));
}

/*Command for put*/
if(strcmp(request,"put")==0)
{   bzero(request,sizeof(request));
    bzero(list,sizeof(list));
    printf("Please enter filename:\n");
    scanf("%s",list);
    //printf("%s",list);

    if (send(sock,list,sizeof(list), 0)!= sizeof(list))
    perror("send() sent a different number of bytes than expected");

    fp=fopen(list,"r");

    if(fp==NULL)

    {
    puts ( "Cannot open target file" ) ;
        fclose (fp) ;
        exit(0);
    }

    while(!feof(fp))
    {
    bzero(b,sizeof(b));
    int was_read = fread(b, sizeof(char),50,fp);

    if (send(sock,b,(sizeof (char) * was_read), 0)!= (sizeof (char) * was_read))
    perror("send() sent a different number of bytes than expected");
    }   

    zero(b,sizeof(b));
    if (send(sock,b,sizeof(b), 0)!= sizeof(b))
    perror("send() sent a different number of bytes than expected");

}

}while (strcmp(request,"end")!=0);

close(sock); /* Close socket */
exit(0);
}
4

1 回答 1

1

一种方法是让客户端在文件末尾关闭套接字。服务器将成功从 接收 0 个字节recv(),这意味着另一端干净地关闭了套接字。我注意到您当前没有在服务器代码中检测到此返回值,但您应该检测到。

我注意到您的协议能够请求多个文件。在这种情况下,您需要在发送实际文件之前发送文件中的字节数,然后服务器将知道需要多少字节。或者,您可以像 FTP 一样为文件数据打开第二个套接字连接(一次一个文件)。

作为文体说明,代码中的缩进很糟糕。很难阅读以找出块的开始和结束位置。纯粹出于格式化的原因,我会在代码审查中拒绝此代码。

于 2012-11-06T01:13:58.613 回答