0

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");
  }
Arjun Mathew Dan
  • 5,240
  • 1
  • 16
  • 27
jinhwan
  • 1,207
  • 1
  • 13
  • 27

3 Answers3

3

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

user207421
  • 305,947
  • 44
  • 307
  • 483
0
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
}
user3629249
  • 16,402
  • 1
  • 16
  • 17
-1

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

Community
  • 1
  • 1
Yasir Majeed
  • 739
  • 3
  • 12
  • You've contradicted yourself. *Either* the write blocks if the send buffer is full, and returns when all the bytes are written, which is the case, and the reason for this question, *or* it returns with a lesser count, which is not the case in blocking mode. The Posix specification mandates the former, contrary to what the documentation you've cited says. If it really behaved like that, this question wouldn't have been asked. – user207421 Mar 27 '15 at 05:33
  • I just asked him to make sure this isn't happening. I never said that it must happen that write() will return with lesser bytes. I just asked him to make sure that the documentation thing really doesn't happen always. For learners, they must explore all the possibilities. You are forcing him to limit his thinking. Negative approach... – Yasir Majeed Mar 27 '15 at 05:48
  • Don't be ridiculous. I am saving him some trouble by eliminating a possibility that will never happen from the things you claim he should make sure of. There is nothing 'negative' about that. – user207421 Mar 27 '15 at 17:06
  • Oh realy??? You mean to say that he should not realy even think of what documentation says?? Thats very very positive – Yasir Majeed Mar 27 '15 at 17:28