【问题标题】:How to terminate connection immediately on long polling如何在长轮询时立即终止连接
【发布时间】:2021-06-25 16:31:03
【问题描述】:

商店有连接到 LAN 上的 192.168.1.68 的客户显示器。 它使用长轮询来使用 http POST 接收显示数据。

它显示发送的数据,但 HttpSendRequest 需要 5 次发送才能返回。 我将超时设置为 60 毫秒并将重试次数设置为 1,但在 HttpSendRequest 完成之前仍需要 5 秒。

如果 timeout 的值更大,HttpSendRequest 会等待更长的时间。

为什么 HttpSendRequest 不能等待少于 5 秒?

如何在数据发送后立即终止调用,以便单线程应用程序可以继续。命令

curl -d "@duedata.json" -H "Content-Type: application/json; charset=utf-8" --max-time 2 -X POST http://192.168.1.92:8082/poll-command

需要 2 秒并在 PCU 中显示数据。数据发送到显示器需要 1.2 秒。

FUNCTION HTTPGetEx
LPARAMETERS tcPage, tcBuffer, tnBufferSize, tcHeaders, tcFileName, lpost


DECLARE INTEGER HttpOpenRequest ;
   IN WININET.DLL ;
   INTEGER hHTTPHandle,;
   STRING lpzReqMethod,;
   STRING lpzPage,;
   STRING lpzVersion,;
   STRING lpzReferer,;
   STRING lpzAcceptTypes,;
   INTEGER dwFlags,;
   INTEGER dwContextw

hHTTPResult=HttpOpenRequest(THIS.hhttpsession,;
   Icase(VARTYPE(lpost)='C', lpost, lpost or  tnPostSize > 0, "POST","GET"),;
   tcPage,;
   NULL,NULL,NULL,;
   INTERNET_FLAG_RELOAD + ;
   IIF(THIS.lsecurelink,INTERNET_FLAG_SECURE,0) + ;
   this.nHTTPServiceFlags,0) 

*** Apply timeout to the HTTP connection handle
THIS.wininetsettimeout(THIS.nConnectTimeOut,hHTTPResult)
THIS.wininetsettimeout(THIS.nConnectTimeOut)

THIS.hhttpsession=hHTTPResult

DECLARE INTEGER HttpSendRequest    ;
   IN WININET.DLL ;
   INTEGER hHTTPHandle,;
   STRING lpzHeaders,;
   INTEGER cbHeaders,;
   STRING lpzPost,;
   INTEGER cbPost

dwTimeoutSecs = 60

llRetVal=InternetSetOption(hHTTPResult,;
   INTERNET_OPTION_RECEIVE_TIMEOUT,;
   @dwTimeoutSecs,4)

llRetVal=InternetSetOption(hHTTPResult,;
   INTERNET_OPTION_SEND_TIMEOUT,;
   @dwTimeoutSecs,4)


dwTimeoutSecs=1  &&// Retry only 1 time
llRetVal=InternetSetOption( hHTTPResult,;
      INTERNET_OPTION_CONNECT_RETRIES,;
      @dwTimeoutSecs,4)

? 'Before HttpSendRequest'
* Todo: why HttpSendRequest takes 5 seconds ?
lnRetval=HttpSendRequest(hHTTPResult,tcHeaders,LEN(tcHeaders),lcPostBuffer,tnPostSize)
? 'After HttpSendRequest'

【问题讨论】:

  • 从客户端的角度来看,您只能通过使用InternetCloseHandle 例程来中止/断开当前操作。参考:How can I abort a request sent using wininet?
  • Visual FoxPro 是单线程的。应用程序没有收到控制权来执行它。它等待 WinAPI 调用完成。为什么不接受超时值?如何强制 winapi 在 2 秒后返回,而不是在 5 秒后返回?

标签: http winapi winsock visual-foxpro long-polling


【解决方案1】:

使用winhttprequest:

查看https://docs.microsoft.com/en-us/windows/win32/winhttp/iwinhttprequest-settimeouts

Clear
owinhttp  = Create('winhttp.winhttprequest.5.1')
owinhttph = Create("winhttpH")
Eventhandler(owinhttp,owinhttph)

url = 'https://stackoverflow.com/questions/66857697/how-to-terminate-connection-immediately-on-long-polling'

Try

    With owinhttp
* resolveTimeout,connectTimeout,sendTimeout,receiveTimeout: 
        .setTimeOuts(2000,30000,30000,60000)
        .Open('GET',url,.F.)
        .setrequestheader('Connection','keep-alive')
        .Send()
    Endwith

Catch

    Aerror(ae)
    If ae(1,1) # 1429
        Display Memory Like ae
    Endif

Endtry


*****************************************************
Define Class winhttph As Session OlePublic
*****************************************************

    Implements iwinhttprequestevents In winhttp.winhttprequest.5.1
    bytesrec = 0
    cData = ''

*-------------------------------------------------------------------------------------
Procedure iwinhttprequestevents_onresponsedataavailable(Data As variant) As void
*-------------------------------------------------------------------------------------

    This.bytesrec = This.bytesrec+Len(Data)
    This.cData = This.cData+Data

    ? 'Bytes received:',This.bytesrec
    ? Strconv(Data,11)

    If This.bytesrec > 2000
        owinhttp.abort()
        Strtofile(Ttoc(Datetime())+Chr(13)+This.cData,'test.txt')
        Modify File test.txt Nowait
    Endif

*--------------------------------------------------------------------
Procedure iwinhttprequestevents_onresponsestart(Status As Number, contenttype As String) As void
*--------------------------------------------------------------------

*--------------------------------------------------------------------
Procedure iwinhttprequestevents_onerror(errornumber As Number, errordescription As String) As void
*--------------------------------------------------------------------
if errorNumber # -2147024890
    ? 'ERROR',errornumber,errordescription,'url:'+url
endif

*--------------------------------------------------------------------
Procedure iwinhttprequestevents_onresponsefinished() As void
*--------------------------------------------------------------------

********************************************
Enddefine
********************************************


    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-22
    • 1970-01-01
    • 2014-09-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多