Problem with read & write

Hello mates:

I met problem with using read() & write(). I m trying to use read twice on client first time is the size of buffer, 2nd time is the buffer. I think I have to, coz I dnot know file size. So, I write twice on server as well -- 1st, filesize; 2nd, buffer.

The problem is, sometimes, I cannot get anything at 2nd time. The file I got is empty, nothing. However, if I put a sleep(1) before the 2nd write() on server, I can read( but this sometimes may cause a segmentation fault)...

i.e.:
Client Server

   read\(\) 1st                            write\(\) 1st         <-----both OK

                                           \(if I put a sleep\(1\)here, it's OK\)                   

   read\(\) 2d                             write\(\) 2nd         <-----problem

Does anybody know the reason?

BEST REGARDS,

Elton

If you are using sockets send() and recv() offer much greater control over your data transmission

But ordinary read and write should still work, yes? No reason for them to segfault without an error in the program. If my hunch is correct send() and recv() could suffer the same issues...

Check to make sure you're recieving the number of bytes you intended. I think you might be getting crazy numbers for filesize, which could cause the crash.

Try them and if the error disappears then the reason exists :slight_smile:

How so? Even if the error goes away, the program still lacks the error-checking to handle them. It should fail, not crash.

It's really a frustrating problem :frowning:

I m trying to use 2 write() in a row, first write() is used to send file size, 2nd send the file. On client side, I use malloc() for the buf size and free later.

Current situation is if I put sth (like sleep(1) or a read()) btw 2 write() , they both work fine. Othrewise, I lose some bytes on client side which is from the 2nd write(). That makes the browser cannnot recognize the HTTP header....

REGARDS,

ELton

OK, I suggest that you set up a proper handshake. Currently your scenario is like this:
server -- write size
client -- read size
server -- write data_buffer
client -- read data_buffer

Change that to:
server -- write size
client -- read size
client -- write ACK
server -- read ACK
server -- write data_buffer
client -- read data_buffer
client -- write ACK

and so on....
So it will never be that your server is continuously writing to a socket that the client is not able to read cause it crashed...

Thanku blowtorch,

Ye, I think that's a way. But why cannot we use 2 write() in a row? why that could crash read() on client? Do anybody know this?

Chees,

Elton

I do not mean to say that two writes in a row would crash a client. I'm just trying to say that this would be a better way. If there was any error in the read on the client side, the server would be notified of this and would resend the buffer.

Regarding the client side crash, you need to post the code, or atleast the part where the crash is occurring, so that someone could take a look at it. Also, if posting code, please remember to use the code tags. Not using those makes it very difficult to read the code.

Hi guys,

This my problem prone code:

On server side:
.
.
.

void reply(int s, SizedBuffer p, char *type)
{
	SizedBuffer sBuf;
    char *r;
    char l[10], whole[10];
    int dataStart;

    sprintf(l,"%d",p.size);

    dataStart = strlen(header1) + strlen(l) + strlen(header2) + strlen(type);

    r = (char *) calloc(dataStart + p.size + 1, sizeof(char));

    strcat(r,header1);
    strcat(r,l);
    strcat(r,header2);
    strcat(r,type);
    bcopy(p.buffer, r+dataStart, p.size);

        
    /*Write file size to client.*/
    sprintf(whole, "%d", dataStart + p.size);
    whole[strlen(whole)] = '\0';

    write(s, whole, strlen(whole));

   /*problem happens here...*/
    write(s, r, dataStart + p.size);

    free(r);
}
.
.

On client side:
.
.

while(1)
   {
      memset(buf,'\0', BUFFER_SIZE);
      if((newSock = acceptConnection(sp->sock)) == 0)
         exit(-1);
      nread = Read(newSock, buf, BUFFER_SIZE);
      
      if((c = makeClientSocket((sp->count), ipAddr)) == 0)
         exit(-1);

      cSock = c->socket;
      
      Write(cSock, buf, BUFFER_SIZE);
      memset(buf,'\0', BUFFER_SIZE);
      
      Read(cSock, buf, 10);
      fLen = atoi(buf);
      printf("fLen is :%d\n", fLen);
      
	  Write(cSock, buf, 10);
      
      char * file = malloc((fLen)*sizeof(char));
     
     /*problem happens here: I lose some bytes of the buffer.*/
      recv(cSock, file, fLen, MSG_WAITALL);
      
      printf("==> %s\n", file);
      
      write(newSock, file, fLen);
      close(newSock);
	  free(file);
      
   }

.
.

hope you guys can figure it out :slight_smile:

REGARDS,

Elton

That code is missing a great deal, like, what header1, header2, whole, and type is.

      r = (char *) calloc(dataStart + p.size + 1, sizeof(char));
      r[0]='\0';
      strcat(r,header1);

The bit in red is essential for your program to reliably work. When you allocate memory, it's not necessarily blank memory -- there could be anything in it. Meaning, when you use strcat, it tries to append it to the end of what's already in there instead of putting it at the beginning.

A more proper way to do this would be

strcpy(r,header1);

-- which overwrites whatever's in r with no regard for what was in it before, and leaves it's own valid NULL terminator.

Or perhaps even get rid of that mess of strcats -- wasteful, it re-measures the length of the string every time -- with a sprintf:

sprintf(r,"%s%s%s%s",header1,l,header2,type);

Also, this code:

sprintf(whole, "%d", dataStart + p.size);
    whole[strlen(whole)] = '\0';

...hints at a deep misunderstanding of strings in C. strlen won't work unless the string already has a null terminator! The null terminator is what it uses to measure the length of the string; and any standard C string functions, with the exception of strncpy, will always add the null for you.

Also, this:

Read(cSock, buf, 10);

assumes that the length string is 10 bytes long. This also hints at a deep misunderstanding of strings in C... the buffer the server held the string in was 10 bytes, but the actual string it held, and the actual data it sent, could be anything between zero and nine bytes. So in reading the 10 bytes, you're reading past the length string into your binary data.

My suggestion? Throw all that code out, learn how strings work in C, start over. It's not just a program bug, it's a design that can't work.