write()在写入大数据后永远被阻止

时间:2015-03-27 03:42:57

标签: c sockets

写完大数据后,

write()没有得到回复。写一个插座是否有限制?或者它受操作系统的限制?(我在ubuntu上运行了这个)
我自己的代码适用于低于1kb with (5 byte per write, little write number)(1Mb per write, 1 write )尝试的小文件。但该代码不适用于3Mb with (5 byte per write, a lot of write)(1Mb per write, 3 write)尝试的大文件。

例如,3M file with 1Mb per write情况下,第三次写入被永久阻止,无法获得返回值。

下面是我自己的代码。从stdin输入并将其写入服务器。 lprintfl2printf只是'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");
  }

3 个答案:

答案 0 :(得分:3)

接收对等方没有读取数据,因此发送方阻止。

答案 1 :(得分: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
}

答案 2 :(得分:-1)

这种情况是您已经使用了套接字的整个发送缓冲区,并且接收方尚未在其末尾调用recv()。当接收器调用recv()时,底层内核实现将从发送端的发送缓冲区中删除接收到的字节。这将创建更多空间,write()调用中的剩余字节将写入发送缓冲区。写入所有字节后,write()将返回。

在你的情况下,你说写是被阻止的。所以为了避免这种情况,你可以做两件事

  1. 使用ioctl()函数使用非阻塞写入。一个好的起点是http://www.kegel.com/dkftpbench/nonblocking.html
  2. 如果是TCP,您可以增加发送缓冲区。为此,setsockopt()是你的朋友。该选项为SO_SNDBUF。设置发送缓冲区的值足够大,即使接收器在一段时间内没有调用接收,也会成功接收2或3次写入。可以在此处找到示例Understanding set/getsockopt SO_SNDBUF
  3. 希望这能解决您的问题