请看以下代码:#define MAX_BUFFER_SIZE    4096
// Initialize critical section (data) and create 
// an auto-reset event (hEvent) before creating the
// two threads
CRITICAL_SECTION data;
HANDLE           hEvent;SOCKET           sock;
TCHAR            buff[MAX_BUFFER_SIZE];
int              done=0;
// Create and connect sock
...
// Reader thread
void ReadThread(void) 
{
    int nTotal = 0,
        nRead = 0,
        nLeft = 0,
        nBytes = 0;    while (!done)   
    {
        nTotal = 0;
        nLeft = NUM_BYTES_REQUIRED;   

// However many bytes constitutes 
// enough data for processing 
// (i.e. non-zero)
        while (nTotal != NUM_BYTES_REQUIRED) 
        {
            EnterCriticalSection(&data);
            nRead = recv(sock, &(buff[MAX_BUFFER_SIZE - nBytes]),
                nLeft, 0);
            if (nRead == -1)
            {
                printf("error\n");
                ExitThread();
            }
            nTotal += nRead;
            nLeft -= nRead;            nBytes += nRead;
            LeaveCriticalSection(&data);
        }
        SetEvent(hEvent);
    }
}// Computation thread
void ProcessThread(void) 
{
    WaitForSingleObject(hEvent);    EnterCriticalSection(&data);
    DoSomeComputationOnData(buff);
    
    // Remove the processed data from the input
    // buffer, and shift the remaining data to
    // the start of the array
    nBytes -= NUM_BYTES_REQUIRED;    LeaveCriticalSection(&data);
}
问题:
nRead = recv(sock, &(buff[MAX_BUFFER_SIZE - nBytes])填入缓冲区为什么不是从buff[nBytes]开始填入?上面的两个函数分别对应两个线程,一个是读取数据到REQUIRE的程度就通知另一个线程,而另一个是处理线程。

解决方案 »

  1.   

    你要理解nBytes是啥意思,它表示buf中还有多少个字节没有被处理线程处理。
    两个线程公用一个 buf,如果都填都不,那么处理线程还没处理完的时候数据就被读线程把数据覆盖了。
      

  2.   

    刚刚开始接触网络编程,这个实例应该是针对TCP/IP的传输,我觉得比较疑惑的是如果第一次就已经检测到有数据可读的时候,就开始从一个缓冲区的最后开始接受数据,那岂不是会超出缓冲区的范围?是不是winsock里面recv会根据不同的协议然后从缓冲区的最后反方向去读数据?
      

  3.   

    这个实例是windows网络编程里面关于套接字阻塞模式的一种变通方法,就是为了让套接字不要一直等待,应该和数据的处理方向没什么关系。而且这个实例代码我在很多地方都看到了,应该可以确保这个代码是正确的。就是有点疑惑,总感觉这样子会超出缓冲区。
      

  4.   

    整个数据块是分开传输的,你接的时候肯定要把他们组合到一起呀,你nBytes初始值是0,就是从缓冲区的起始位置填数据的,第二次接到的数据肯定要放到第一次的后边了,就是MAX_BUFFER_SIZE - nBytes这个位置
      

  5.   

    第一次接收数据不是从MAX_BUFFER-nBytes(初始时候nBytes=0)也即MAX_BUFFER处开始填入数据吗?那如果一开始就从这里填入数据,那岂不是一开始就超出缓冲区?
      

  6.   

    nBytes代表的是已经读取的数据量,我的疑惑在于怎么一开始就从MAX_BUFFER_SIZE-nBytes(初始nBytes=0)读入数据?这样一开始就应该造成缓冲区溢出了吧?能再解释一下你的想法吗?谢谢你。
      

  7.   

    你改成
    nRead = recv(sock, buff + nBytes,  nLeft, 0);
    试试,nRead = recv(sock, &(buff[MAX_BUFFER_SIZE - nBytes]),
      nLeft, 0);
    应该会越界。
      

  8.   

    你的想法确实和我一样,只是我前面说到了,不单只是这本Windows网络编程的中英文版本,或者我在网上搜的相关代码,很多前辈都是这样子写的,所以可以说明代码的正确性是可以保证的,但是搞不明白为什么。
      

  9.   

    nBytes -= NUM_BYTES_REQUIRED;
    nBytes += nRead;
    你仔细琢磨一下就明白了  nRead 是实际读的字节数  仔细看代码就明白了  
      

  10.   

    还有 ;(buff[MAX_BUFFER_SIZE - nBytes]),  你自己看看 这个程序肯定不会溢出的 一减一加的 肯定不会溢出 
      

  11.   

    刚开始nBytes=0,那MAX_BUFFER_SIZE-nBytes不就等于MAX_BUFFER_SIZE?那buff[MAX_BUFFER_SIZE]开始不就超出了缓冲区?能不能再说一下,也许我没明白你的意思。
      

  12.   


    应该是错误的,很多书上有错误的代码。
    应该是&buff[nBytes]看书要有辨别能力
      

  13.   

    我也不明白为什么要这样,有2个地方:
    1.楼主说的 recv(sock, &(buff[MAX_BUFFER_SIZE - nBytes]),最开始的时候nbytes是0,那不是从buf最后面开始接收吗,这样不明显报错吗?
    2.while (nTotal != NUM_BYTES_REQUIRED) 判断是否达到请求的数量。这个怎么确定呢?如何准确的确定有多少个要接收的?如果不能确定,不是一直循环在这了吗?
    3。当接收完要请求的数量后,while退出,也就是nTotal == NUM_BYTES_REQUIRE,SetEvent,处理线程开始工作。nBytes -= NUM_BYTES_REQUIRED;这样能使接收线程开始工作吗,也就是符合.while (nTotal != NUM_BYTES_REQUIRED)?如果这个条件不成立的时候,接收线程,不是一直在SetEvnet这个吗,不变成独占CPU了?