2012-11-04 75 views
0

我用send和recv通過客戶端和服務器之間的郵件保存的全部內容。在服務器端,當我收到一條消息,上緩衝FNAME保存的信息是不是已經從客戶端發送的整個消息的recv不會在緩衝

服務器

#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 fname[128]; 
char request[1024]; 
char op[1000]; 
char command[5]; 
FILE *fp; 
DIR *dp; 
char list[1024]; 
int port,sock,newsock,serverlen,clientlen,fname_len,recvMsgSize,i; 
char buf[256]; 

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); 

strncpy(command,request,4); 
printf("%s\n",command); 
/*IF YOU ARE GOING TO EXECUTE AN LS COMMAND*/ 

if (strcmp(command,"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(command,"put")==0) 
{ 
printf("execute put!!\n"); 

bzero(fname, sizeof fname); /* Initialize buffer */ 

if ((recvMsgSize = recv(newsock,fname,128, MSG_WAITALL)) < 0) 
perror("recv() failed"); 

printf("%s!!!!\n",fname); 

} 
}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(1) */ 


} 

CLIENT

#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; 
int fname_len,msg_len,request_len; 
char buf[256]; 
char fname[128]; 
char request[1204]; 
char list[1024]; 
char msg[512]; 
char op[1000]; 
char temp[5]; 
char *temp3; 
FILE *fp; 


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); 

request_len=sizeof(request); 

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

strncpy(temp,request,4); 
printf("%s\n",temp); 

if(strcmp(temp,"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); 
     } 
} 
} 

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

if (send(sock,fname,128, MSG_DONTWAIT)!= 128) 
perror("send() sent a different number of bytes than expected"); 

} 
}while (strcmp(request,"end")!=0); 
close(sock); /* Close socket */ 
exit(0); 
} 

回答

4

當你調用recv ,你需要檢查收到的字節數。如果它小於您要求的值,則需要再次調用recv,並將其添加到先前接收的緩衝區的末尾。可能發生的情況是,當您第一次致電recv時,只有部分信息已到達。

char buf[N]; 
char* p = buf; 
ssize_t bytesRemaining = N; 
while (bytesRemaining) { 
    ssize_t recvd; 
    recvd = recv(sock, p, bytesRemaining, 0); 
    bytesRemaining -= recvd;  // keep track of bytes left 
    p += recvd;     // advance buffer pointer 
} 
+0

喜喬納森和THX的快速回復。我做你建議的修正,但仍然問題是不固定的。 – Giannos

+0

你有沒有把一些調試消息,看看'recv'被多次調用?該代碼樣的*已經*的工作。如果沒有可用數據,'的recv()'將阻止。所以,要麼你會得到所有你想要的數據,或者該程序將簡單地掛起,等待數據。 –

+0

是的,我沒有和我注意到,只調用一次 – Giannos

1

永遠不能依靠recv()函數接收一次調用中的所有數據。您可能需要多次調用它在一個循環中獲取的所有數據(等於數據的長度。

+0

這是Jonathon的建議,但仍然是同樣的問題。有什麼建議麼? – Giannos