【问题标题】:write() is blocked forever after writing big datawrite() 写入大数据后被永久阻塞
【发布时间】:2015-05-31 07:44:09
【问题描述】:

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 输入并将其写入服务器。 lprintf,l2printf 只是'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");
  }

【问题讨论】:

  • 另一端是否在读取数据?
  • @EdHeal 上面的代码是client.c。实际上我通过'client.c
  • @EdHeal 正在向您询问另一端的情况。服务器。
  • 使用write() 而不是send() 用于套接字看起来很奇怪,有人知道除了标志中隐含的0 之外是否有区别?
  • @Havenard 没有区别。 write(sd,buffer,length) 等价于send(sd,buffer,length,0);

标签: c sockets


【解决方案1】:

接收端没有读取数据,所以发送端阻塞。

【讨论】:

    【解决方案2】:

    这种情况是您已经消耗了套接字的整个发送缓冲区,而接收方尚未在其末尾调用 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

    希望这能解决您的问题

    【讨论】:

    • 你自相矛盾。 要么 如果发送缓冲区已满,则写入阻塞,并在写入所有字节时返回,这是这种情况,以及此问题的原因,它返回计数较少,在阻塞模式下不是这种情况。 Posix 规范要求前者,这与您引用的文档所说的相反。如果真的是这样,就不会问这个问题了。
    • 我只是让他确保这不会发生。我从来没有说过 write() 一定会以更少的字节返回。我只是让他确保文档的事情不会总是发生。对于学习者来说,他们必须探索所有的可能性。你在强迫他限制他的想法。消极态度...
    • 别开玩笑了。我通过消除您声称他应该确保的事情中永远不会发生的可能性来为他节省一些麻烦。没有什么“负面”的。
    • 哦,真的吗???你的意思是说他不应该真的去想文件说什么??这是非常非常积极的
    【解决方案3】:
    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
    }
    

    【讨论】:

      猜你喜欢
      • 2017-06-06
      • 1970-01-01
      • 1970-01-01
      • 2017-01-04
      • 1970-01-01
      • 1970-01-01
      • 2016-09-23
      • 1970-01-01
      • 2013-05-15
      相关资源
      最近更新 更多