Giannos
Giannos

Reputation: 11

recv does not save the whole message in the buffer

I use send and recv to pass messages between a client and a server. On the server side when i receive a message on buffer fname the message saved is not the whole message that has been sent from client

SERVER

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

Upvotes: 0

Views: 1133

Answers (2)

Jonathon Reinhart
Jonathon Reinhart

Reputation: 137398

When you call recv, you need to check the number of bytes received. If it is less than you asked for, you need to call recv again, and add to the end of the previously received buffer. What is probably happening, is that only part of the message has arrived when you first call 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
}

Upvotes: 4

Aniket Inge
Aniket Inge

Reputation: 25695

One can never rely on recv() function receiving all the data in one instance of the call. You might have to call it repeatedly in a loop to fetch all the data(equal to the length of the data.

Upvotes: 1

Related Questions