簡體   English   中英

OpenSSL非阻塞套接字SSL_read()不可預測

[英]OpenSSL Non-Blocking Socket SSL_read() unpredictable

我正在嘗試使用OpenSSL創建一個非阻塞套接字,以便可以遍歷SSL_read()直到沒有剩余數據,然后中斷該循環。 經過大量工作,我終於使連接正常工作,但是現在對於前一千次迭代,SSL_read()將返回-1。 之后,它將為我提供套接字上的實際數據。 SSL_read()也不返回讀取的准確字節數,即使它正在讀取正確的字節,它也總是說-1。 我能夠使其在使用阻塞套接字的情況下正常工作,但非阻塞似乎有問題...

char *sslRead (connection *c)
{
const int readSize = 1024;
char *rc = NULL;
int r;
int received = -1, count = 0;
int TotalReceived = 0, ReallocSize = 0;
char buffer[1024];

if (c)
{
    while (1)
    {

        received = SSL_read (c->sslHandle, buffer, readSize);

    buffer[received] = '\0';

        TotalReceived += received;
        printf("Buffsize - %i - %s \n", received, buffer);


        if (received <= 0)
        {

            // this line added per advice of Eric Tsui but does not
            // change behaviour 
            received = SSL_read (c->sslHandle, buffer, readSize);



            //printf(" received equal to or less than 0\n")
            switch (SSL_get_error(c->sslHandle, received))
            {
                case SSL_ERROR_NONE:
                {
                        printf("SSL_ERROR_NONE %i\n", count);
                        //if (received != -1)
                        //  goto END;
                        break;
                }   
                case SSL_ERROR_ZERO_RETURN: 
                {
                        printf("SSL_ERROR_ZERO_RETURN %i\n", count);
                        goto END;
                        break;
                }   
                case SSL_ERROR_WANT_READ: 
                {
                        printf("SSL_ERROR_WANT_READ %i\n", count);

                        break;
                }
                case SSL_ERROR_WANT_WRITE: 
                {
                        printf("SSL_ERROR_WANT_WRITE %i\n", count);
                        goto END;
                        //break;
                }
                default:
                {
                        printf("error %i\n", received); 
                        break;
                }
            }     


            count++;
        }
    }
}
END:
return rc;
}

如果您之前已經做過,那么如果您能告訴我這段代碼有什么問題,我將不勝感激。 謝謝。

您的循環調用SSL_read()次數過多,並且當確實沒有更多數據要讀取時( SSL_ERROR_WANT_READ條件),錯誤處理不會中斷循環。 嘗試類似這樣的方法:

char *sslRead (connection *c)
{
    const int readSize = 1024;
    char *rc = NULL;
    int received, count = 0;
    int TotalReceived = 0;
    fd_set fds;
    struct timeval timeout;
    char buffer[1024];

    if (c)
    {
        while (1)
        {
            received = SSL_read (c->sslHandle, buffer, readSize);
            if (received > 0)
            {
                TotalReceived += received;
                printf("Buffsize - %i - %.*s \n", received, received, buffer);
            }
            else
            {
                count++;

                //printf(" received equal to or less than 0\n")
                int err = SSL_get_error(c->sslHandle, received);
                switch (err)
                {
                    case SSL_ERROR_NONE:
                    {
                        // no real error, just try again...
                        printf("SSL_ERROR_NONE %i\n", count);
                        continue;
                    }   

                    case SSL_ERROR_ZERO_RETURN: 
                    {
                        // peer disconnected...
                        printf("SSL_ERROR_ZERO_RETURN %i\n", count);
                        break;
                    }   

                    case SSL_ERROR_WANT_READ: 
                    {
                        // no data available right now, wait a few seconds in case new data arrives...
                        printf("SSL_ERROR_WANT_READ %i\n", count);

                        int sock = SSL_get_rfd(c->sslHandle);
                        FD_ZERO(&fds);
                        FD_SET(sock, &fds);

                        timeout.tv_sec = 5;
                        timeou.tv_nsec = 0;

                        err = select(sock+1, &fds, NULL, NULL, &timeout);
                        if (err > 0)
                            continue; // more data to read...

                        if (err == 0) {
                            // timeout...
                        } else {
                            // error...
                        }

                        break;
                    }

                    case SSL_ERROR_WANT_WRITE: 
                    {
                        // socket not writable right now, wait a few seconds and try again...
                        printf("SSL_ERROR_WANT_WRITE %i\n", count);

                        int sock = SSL_get_wfd(c->sslHandle);
                        FD_ZERO(&fds);
                        FD_SET(sock, &fds);

                        timeout.tv_sec = 5;
                        timeou.tv_nsec = 0;

                        err = select(sock+1, NULL, &fds, NULL, &timeout);
                        if (err > 0)
                            continue; // can write more data now...

                        if (err == 0) {
                            // timeout...
                        } else {
                            // error...
                        }

                        break;
                    }

                    default:
                    {
                        printf("error %i:%i\n", received, err); 
                        break;
                    }
                }     

                break;
            }
        }
    }

    return rc;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM