File Xfer thru socket loses last \n

File Xfer thru socket loses last \n

Post by Tim » Thu, 21 Mar 2002 14:43:47



Greetings,

Working a class project and having a problem.  I have a client/server
communitcating via STREAM sockets.  I can open a file and read it into a
buffer on the client side, send it to the server and write it to disk, but
it always loses the trailing \n on the revc side.  Send(), recv(), and
write() all return the same number of bytes, but still no \n.  Any tips from
the experts?

One other thing.  On the server side, I have 2 open sockets plus stdin,
stdout and stderr, but when I make the call to open() it returns fd1 instead
of 5.  Another subsequent open(), however produces fd6.  I'm confused.

Thanks.
Tim

 
 
 

File Xfer thru socket loses last \n

Post by John Gordon,217-352-6511x7418,CEERD-CF- » Thu, 21 Mar 2002 23:10:37



> Working a class project and having a problem.  I have a client/server
> communitcating via STREAM sockets.  I can open a file and read it into a
> buffer on the client side, send it to the server and write it to disk, but
> it always loses the trailing \n on the revc side.  Send(), recv(), and
> write() all return the same number of bytes, but still no \n.  Any tips from
> the experts?

there's a bug in your code.  but we can't tell what the bug is unless
you post it.

---
John Gordon                  "No Silicon Heaven?  Preposterous!  Where would


 
 
 

File Xfer thru socket loses last \n

Post by Tim Burk » Fri, 22 Mar 2002 04:53:04


<John Gordon>; <217-352-6511x7418>; "CEERD-CF-N"

<gor...@osiris.cso.uiuc.edu> wrote in message

news:xL0m8.31215$tg4.363619@vixen.cso.uiuc.edu...
> "Tim" <tim.bur...@NOSPAM.cox.net> writes:

> > Working a class project and having a problem.  I have a client/server
> > communitcating via STREAM sockets.  I can open a file and read it into a
> > buffer on the client side, send it to the server and write it to disk,
but
> > it always loses the trailing \n on the revc side.  Send(), recv(), and
> > write() all return the same number of bytes, but still no \n.  Any tips
from
> > the experts?

> there's a bug in your code.  but we can't tell what the bug is unless
> you post it.

OK, I figured this was probably something common, so I didn't post it all.
Anyway, see below....  BTW, the intent here is not to write a bullet-proof
app, rather this is a class on SE management and we are exploring XP as a
process.  This app is the vehicle for that exploration.

Thanks.
Tim

The client side
/**************************************************************************
**
** CEN6055
**
** Author: Team B:
**
** File Information: %W%-%G%
**
** Description
**
** Revision
**
**************************************************************************/
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <netdb.h>

#include "socket.h"

/***********************/
/* function prototypes */
/***********************/
int SendArgsToServer(int sockfd, int argc, char *argv[]);
int FileOpen(char *filename, int *size);
int SendFile(int sockfd, int fd, int size);

/************************************************************************/
/* The following #ifdef statement is used to insert the test code       */
/* into the module.  If inserted, it replaces the regular main function */
/************************************************************************/
#ifdef UNIT_TEST
#include "t_handin.c"
#else

/***************************************************************
**
** Function Name: main
**
** Description:
**     This is the starting point of the handin client program.
**
** Arguments:
**     argc - number of parameters
**     argv - parameter list
**
** Returns:
**     status - success or failure status of the command
**
** Functions Used:
**
***************************************************************/
int main(int argc, char *argv[])
{
    int sockfd;
    int fd;
    int size;

    /*****************************/
    /* Check number of arguments */
    /*****************************/
    if (argc != 5)
    {
        fprintf(stdout,"usage: %s course assgn student file\n",argv[0]);
        exit(-1);
    }

    /*****************/
    /* Create socket */
    /*****************/
    if ((sockfd = CreateSocket()) < 0)
    {
        fprintf(stdout,"%s: error creating socket\n",argv[0]);
        exit(-3);
    }

    /*********************/
    /* Connect to server */
    /*********************/
    if ((ConnectToServer(sockfd,SERVER,THEPORT)) < 0)
    {
        fprintf(stdout,"%s: cannot connect to server\n",argv[0]);
        close(sockfd);
        exit(-4);
    }

    /*****************************/
    /* Send parameters to server */
    /*****************************/
    if (SendArgsToServer(sockfd,argc,argv) < 0)
    {
        fprintf(stdout,"%s: invalid parameters\n",argv[0]);
        close(sockfd);
        exit(-8);
    }

    /****************************************/
    /* Check existence of specified file(s) */
    /****************************************/
    if ((fd = FileOpen(argv[4],&size)) < 0)
    {
        fprintf(stdout,"%s: cannot open '%s'\n",argv[0],argv[4]);
        exit(-9);
    }

    if (SendFile(sockfd, fd, size) < 0)
    {
        fprintf(stderr,"error\n");
    }

    close(fd);
    close(sockfd);
    return(0);

}

#endif

/***************************************************************
**
** Function Name: SendArgsToServer
**
** Description:
**     This function sends the arguments of the program to
**     the server for verification
**
** Arguments:
**     sockfd - valid socket connected to a server
**     argc - number of parameters
**     argv - parameter list
**
** Returns:
**     status - success or failure status of the command
**
** Functions Used:
**
***************************************************************/
int SendArgsToServer(int sockfd, int argc, char *argv[])
{
    char buffer[MAXBUFSIZE];
    int status = 0;

    /************************************/
    /* Create message to send to server */
    /************************************/
    memset(buffer,0,sizeof(buffer));
    sprintf(buffer,"%s %s %s %s",argv[1],argv[2],argv[3],argv[4]);

    /****************************/
    /* Error check send command */
    /****************************/
    if (send(sockfd,buffer,strlen(buffer),0) == -1)
        status = -1;
    else
    {

        /*********************************************/
        /* If message sent ok, wait for confirmation */
        /*********************************************/
        memset(buffer,0,sizeof(buffer));
        if (recv(sockfd,buffer,sizeof(buffer)-1,0) == -1)
            status = -2;
        else
        {
            /***********************************/
            /* Check for validity of arguments */
            /***********************************/
            if (strcmp(buffer,"bad") == 0)
                status = -3;
        }
    }

    return(status);

}

/***************************************************************
**
** Function Name: FileOpen
**
** Description:
**     This function attempts to open a file descriptor to
**     to the specified file and retrieve the size of the file
**
** Arguments:
**     filename - name of the file to open
**     size - will contain the size of the file
**
** Returns:
**     file descriptor to specified file on success
**     size will contain size of file in bytes on success
**     -1 = unable to open file
**     -2 = unable to retrieve file information
**
** Functions Used:
**     None
**
***************************************************************/
int FileOpen(char *filename, int *size)
{
    struct stat buf;
    int fd;

    /*********************************************/
    /* Open a file descriptor for specified file */
    /*********************************************/
    if ((fd = open(filename,O_RDONLY)) >= 0)
    {

        /************************/
        /* Get file information */
        /************************/
        if ((fstat(fd,&buf)) < 0)
        {
            close(fd);
            fd = -2;
        }
        else
            *size = buf.st_size;
    }
    else
        fd = -1;

    return(fd);

}

/**************************************************************/
int SendFile(int sockfd, int fd, int size)
{
    char buffer[MAXBUFSIZE];
    char *filebuf = NULL;

    int status = 0;
    int numread = 0;
    int cursent = 0;
    int totsent = 0;

    /****************************/
    /* Send file size to server */
    /****************************/
    memset(buffer,0,sizeof(buffer));
    sprintf(buffer,"%d", size);
    send(sockfd,buffer,sizeof(buffer),0);

    /****************************/
    /* Send file to server      */
    /****************************/
    fprintf(stderr, "Client says size is: %d\n", size);

    filebuf = (char *) calloc(size, sizeof(char));
    if (filebuf == NULL)
        fprintf(stderr, "Error memory allocation failure\n");
    numread = read(fd, filebuf, size);
    fprintf(stderr, "Client says bytes read: %d\n", numread);
    while (totsent < numread)
      {

        cursent = send(sockfd, filebuf, numread, 0);
        fprintf(stderr, "Client says cursent is: %d \n ", cursent);
        totsent += cursent;
        numread -= cursent;
      }
    return(status);

}

The server
/*********************************************************
**
** CEN6055
**
** Author: Team B:
**
**
** File Information: %W%-%G%
**
** Description:
**     This file contains the code for the server side
**     part of the HandIn program
**
** Revisions:
**
***************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#include "socket.h"

/***********************/
/* function prototypes */
/***********************/
int CheckDirectory(char *directory);
int AcceptFromClient(int sockfd);
int ValidateParms(char *buf, char *pathbuf);
int WriteFile(int sockfd, char *pathdat, char *sizedat);

/***********************************************************************/
/* The following define statement is used to insert the test code      */
/* into the module. If inserted, it replaces the regular main function */
/***********************************************************************/
#ifdef UNIT_TEST
#include "t_handind.c"
#else

/***************************************************************
**
** Function Name: main
**
** Description:
**     This is the starting point of the handind server program.
**
** Arguments:
**     argc - number of parameters
**     argv - parameter list
**
** Returns:
**     status - success or failure status of the command
**
** Functions Used:
**
***************************************************************/
int main(int argc, char *argv[])
{
    int sockfd;    /* socket file descriptor */

    /******************************************/
    /* The number of parameters: program-name */
    /* and toplevel directory for files       */
    /******************************************/
    if (argc != 2)
    {
        fprintf(stdout,"usage: %s directory-name\n",argv[0]);
        exit(-1);
    }
...

read more »

 
 
 

File Xfer thru socket loses last \n

Post by Barry Margoli » Fri, 22 Mar 2002 06:42:58




>int SendArgsToServer(int sockfd, int argc, char *argv[])
>{
>    char buffer[MAXBUFSIZE];
>    int status = 0;

>    /************************************/
>    /* Create message to send to server */
>    /************************************/
>    memset(buffer,0,sizeof(buffer));
>    sprintf(buffer,"%s %s %s %s",argv[1],argv[2],argv[3],argv[4]);

You don't have any delimiter at the end of the last arg.  How is the server
supposed to tell where it ends?  Remember, TCP is a byte-stream protocol,
not a message protocol.  Perhaps you should put a newline at the end of the
message, so the server can read until it gets a newline.

Quote:>/**************************************************************/
>int SendFile(int sockfd, int fd, int size)
>{
>    char buffer[MAXBUFSIZE];
>    char *filebuf = NULL;

>    int status = 0;
>    int numread = 0;
>    int cursent = 0;
>    int totsent = 0;

>    /****************************/
>    /* Send file size to server */
>    /****************************/
>    memset(buffer,0,sizeof(buffer));
>    sprintf(buffer,"%d", size);
>    send(sockfd,buffer,sizeof(buffer),0);

Do you really want to use sizeof(buffer) as the amount to send?  This will
send the size followed by lots of NUL characters (you didn't post your
header file, so I don't know how big MAXBUFSIZE is).  

You should probably change that to strlen(buffer), and as above, put a
newline after the file size.

Quote:>    /****************************/
>    /* Send file to server      */
>    /****************************/
>    fprintf(stderr, "Client says size is: %d\n", size);

>    filebuf = (char *) calloc(size, sizeof(char));
>    if (filebuf == NULL)
>        fprintf(stderr, "Error memory allocation failure\n");
>    numread = read(fd, filebuf, size);
>    fprintf(stderr, "Client says bytes read: %d\n", numread);
>    while (totsent < numread)
>      {

>        cursent = send(sockfd, filebuf, numread, 0);

Each time through this loop you send the beginning of filebuf, rather than
continuing from where the last send ended.  It should be:

        cursent = send(sockfd, filebuf+totsent, numread, 0);

Quote:>        fprintf(stderr, "Client says cursent is: %d \n ", cursent);
>        totsent += cursent;
>        numread -= cursent;
>      }
>    return(status);

...

Quote:>int AcceptFromClient(int sockfd)
>{
...
>        /*****************************************/
>        /* First input should be four parameters */
>        /*****************************************/
>        memset(buf,0,sizeof(buf));
>        if ((numbytes = recv(new_sockfd,buf,sizeof(buf)-1,0)) == -1)

You're assuming that everything that was sent in the client's send() call
will show up with a single recv() call.  That's true of datagram sockets,
not stream sockets.  Just as you need to call send() repeatedly in the
client, you have to call recv() repeatedly in the server.  That's why it's
important to have a delimiter, so the server can tell when it has received
the four parameters.

Quote:>        /**********************/
>        /* Received file size */
>        /**********************/
>        memset(buf,0,sizeof(buf));
>        if ((numbytes = recv(new_sockfd,buf,sizeof(buf)-1,0)) == -1)

Again, you're assuming that the recv() size will be the same as the send()
amount.  If MAXBUFSIZE is big, there's a good chance that the send will be
broken up into multiple packets (Ethernet MTU is about 1500 bytes), and
recv() will probably only return the data from the first packet.  As a
result, when WriteFile() is reading the rest of the data, it will treat all
the remaining NUL bytes in this message as if they were the beginning of
the file being sent, and it will ignore some of the bytes at the end of the
file.

--

Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

 
 
 

1. AOL IM/MSN Messenger file xfer thru ipchains

Hey guys,

Any hints on getting AIM/MSN Messenger file transfers to work thru a nated
ipchians box to internal machines? My friend has a linksys router and
doesn't have any problems, I would think a nated linux box should have the
same capabilities!

Thanks ...

2. capturing commands + their output

3. Lost last data from socket-send()

4. Fileselector

5. Passing file descriptors thru rexec() socket

6. Trouble with Rotate

7. OOB socket xfer and SIGURG

8. xringd and multiple telephone companies

9. Removing last character from last line in a file

10. Lost data while printing thru Xyplex

11. login thru modem loses data

12. kernel 1.3.10 crash, lost inodes and lost files

13. kernel mem crash, lost inodes and lost files