jinhwan
jinhwan

Reputation: 1227

write() is blocked forever after writing big data

write() doesn't get response after writing big data. Are there any limit for writing over one socket? Or is it limited by OS?(I ran this on ubuntu)
My own code works for small file lower than 1kb with (5 byte per write, little write number) or (1Mb per write, 1 write ) attempt. But the code doesn't work for big file about 3Mb with (5 byte per write, a lot of write) or (1Mb per write, 3 write) attempt.

For example, 3M file with 1Mb per write case, third write is blocked forever and can't get return value.

below is actual my own code. input from stdin and write it to server. lprintf,l2printf are just 'log printf'.

int BSIZE = 1024;
  //int BSIZE = 5;
  char buffer[BSIZE];
  int n = 0;
  //phase 2-1 write
  //read from outter

  int bi =0;
  int c;
  int temp= 0;
  int t2 =0;
  while (EOF!=(c = fgetc(stdin))) {
    if(temp++%(1024*1024) == 0){
      l2printf("over 1m\n");
      t2++;
      if (t2 == 2){
        //loglevel=1;
      }
    }
    /*
    if(temp++ > 3500){
      printf("\ntemp 3500\n")
      break;
    }
    */
    lprintf("|");
    lprintf("%x",c & 0xff);

    if(c =='\\'){
      char input[2] = "\\\\";
      lprintf("%x",input[0] & 0xff);

      buffer[bi++] = '\\';
      if(bi == sizeof(buffer)){
        lprintf("\n");
        l2printf ("\nB/1:%x\n", buffer[1]); 
        n = write(sockfd,buffer,sizeof(buffer));
        bi = 0;
      }
      buffer[bi++] = '\\';
      if(bi == sizeof(buffer)){
        lprintf("\n");
        l2printf ("\nB/2:%x\n", buffer[1]); 
        n = write(sockfd,buffer,sizeof(buffer));
        bi = 0;
      }
      //n = write(sockfd,input,sizeof(char)*2);
    } 
    else{
      buffer[bi++] = c;
      if(bi == sizeof(buffer)){
        lprintf("\n");
        l2printf ("\nBc:%x\n", buffer); 
        n = write(sockfd,buffer,sizeof(buffer));
        l2printf("n = %d \n", n);
        bi = 0;
      }
      //n = write(sockfd,&c,sizeof(char));
      //lprintf("%c",c);
    }

    if( n <0 ){
      error("ERROR writing to socket 2-1");
    }
  }
  //adding EOF
  //clear buffer
  lprintf("\n");
  l2printf ("\nEB:%x\n", buffer); 
  n = write(sockfd,buffer,sizeof(char)*bi);
  char input[2] = "\\0";
  n = write(sockfd,input,sizeof(char)*2);
  lprintf("*\\0*");
  if( n <0 ){
    error("ERROR writing to socket 2-1 EOF");
  }

Upvotes: 0

Views: 265

Answers (3)

user3629249
user3629249

Reputation: 16550

there are a number of 'oops' in the posted code.
here is an example, without the logging, etc
but with proper error checking

however, the send() will still hang if the receiver
is not reading the data



// without all the logging, special case for \\, etc
// note: write() is for open files, using a file descriptor
//       so using send() for TCP communication over a socket

#define BSIZE (1024)

char buffer[BSIZE] = {'\0'};
int n = 0;

while( fgets( buffer, BSIZE, stdin );
{
    if( 0 > (n = send(sockfd,buffer,strlen(buffer), 0 ) ) )
    { // then, send failed
        perror( "send for buffer through socket failed" );
        // handle error
    }
} // end while

//adding EOF
// note this is not really EOF, it is a string terminator
//      EOF is supplied automatically when the file is closed
//      by the receiver

char input[2] = {'\0'};
if( 0 > (n = send(sockfd,input,1, 0) ) )
{ // then send failed
    perror( "send for file terminator failed" );
    // handle error
}

Upvotes: 0

Yasir Majeed
Yasir Majeed

Reputation: 741

This is the case that you have consumed the whole send buffer of the socket, and the receiver has not yet called recv() at its end. When the receiver will call recv(), the underlying kernel implementation will remove the received bytes from the send buffer at sender side. This will create more space and the remaining bytes in your write() call will be written to send buffer. When all the bytes are written, write() will return.

In your case you are saying that write is blocked. So to avoid this you can do two things

  1. Use non-blocking write by making use of ioctl() function. A good start point will be http://www.kegel.com/dkftpbench/nonblocking.html
  2. You can increase the send buffer in case of TCP. For this purpose setsockopt() is your friend. The option will be SO_SNDBUF. Set the value of send buffer large enough that at lease 2 or 3 writes are successfull, even if the receiver does not call receive for some time. Example can be found here Understanding set/getsockopt SO_SNDBUF

Hope this will solve your problem

Upvotes: -1

user207421
user207421

Reputation: 311055

The receiving peer is not reading the data, so the sender blocks.

Upvotes: 3

Related Questions