News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

recv in loop

Started by LMZ, August 22, 2005, 06:52:22 AM

Previous topic - Next topic

LMZ

Hi,
i have a problem with loop
i out recv in loop
and want to get server response
but i cant expect the end of this response,
code (part):

.WHILE TRUE
invoke recv, hsocket, offset recv_str, 1500, 0

.IF eax == SOCKET_ERR
   .BREAK
.ELSEIF eax == 0
   .BREAK
.ENDIF

invoke lstrcat, offset big_str, offset recv_str
.ENDW

P1

You need some winproc code to support the message pump.  Then call your recv proc.  Do not loop that code!  The message pump will notify you of new incoming socket data.

This code snippet is part of an SMTP error message notify code ( w/ local echo file ), when transfering a message to the local server.



; ...

.ELSEIF uMsg==WM_SOCKET
            invoke dw2hex, uMsg, addr IPinHEX
            invoke lstrcat, addr OurText, addr szuMsg
            invoke lstrcat, addr OurText, addr IPinHEX
            invoke WriteFileLocal, addr szuMsg
            invoke WriteFileLocal, addr IPinHEX
            invoke dw2hex, wParam, addr IPinHEX
            invoke lstrcat, addr OurText, addr szwParam
            invoke lstrcat, addr OurText, addr IPinHEX
            invoke WriteFileLocal, addr szwParam
            invoke WriteFileLocal, addr IPinHEX
            invoke dw2hex, lParam, addr IPinHEX
            invoke lstrcat, addr OurText, addr szlParam
            invoke lstrcat, addr OurText, addr IPinHEX
            invoke lstrcat, addr OurText, addr crlf
            invoke WriteFileLocal, addr szlParam
            invoke WriteFileLocal, addr IPinHEX
            invoke WriteFileLocal, addr crlf
            INVOKE UpdateWindow, hWnd
            .if ( lParam==FD_WRITE ) && ( wParam == 0 )
                invoke Sending,hWnd
            .elseif lParam==FD_READ
                invoke Receiving,hWnd
            .elseif lParam==FD_CONNECT
                ;mov Send_Ct,0             
            .elseif lParam==FD_CLOSE
                ;invoke MessageBox,0,addr ErrorC,0,MB_OK
                invoke PostMessage,hWnd,WM_DESTROY,NULL,NULL
            .endif

; ...

Receiving proc hWnd:DWORD
invoke RtlZeroMemory, OFFSET Recv_Buff, SIZEOF Recv_Buff
invoke recv,Sock,addr Recv_Buff,SIZEOF Recv_Buff,0
.if eax==SOCKET_ERROR
    invoke MessageBox,0,addr Error8,0,MB_OK
.elseif  eax==0
    jmp Exit_Out   
.else
    ;mov [Recv_Buff + eax + 1],0
    invoke lstrcat, addr OurText, addr szRecd
    invoke lstrcat, addr OurText, addr Recv_Buff
    invoke WriteFileLocal, addr szRecd
    invoke WriteFileLocal, addr Recv_Buff
    INVOKE UpdateWindow, hWnd   
    mov [Recv_Buff + 3],0
    invoke atodw, addr Recv_Buff
    ;mov eMsg_Last, eax
    invoke Intrepret, hWnd, eax
.endif

Exit_Out:
ret
Receiving endp



Sample of Local echo file, also sent to window as OurText.

uMsg = 00000464, wParam = 0000008C, lParam = 00000010
uMsg = 00000464, wParam = 0000008C, lParam = 00000002
uMsg = 00000464, wParam = 0000008C, lParam = 00000001
Recd > 220 Mail Server Fri, 22 Apr 2005 14:35:07 -0500
uMsg = 00000464, wParam = 00000000, lParam = 00000002
Sent > helo MailServer.com
uMsg = 00000464, wParam = 0000008C, lParam = 00000001
Recd > 250 MailServer Hello [XXX.XXX.XXX.XXX]
uMsg = 00000464, wParam = 00000000, lParam = 00000002
Sent > MAIL from:<XXXXXXXXXXX@NoSpam.com>


Regards,  P1  :8)

QvasiModo

Quote from: P1 on August 22, 2005, 02:05:53 PM
You need some winproc code to support the message pump.  Then call your recv proc.  Do not loop that code!  The message pump will notify you of new incoming socket data.

We need to clarify, all this is only valid when using asynchronous sockets.

LMZ

Return Value   If no error occurs, recv() returns the number of bytes received.  If the connection has been closed, it returns 0.  Otherwise, a value of SOCKET_ERROR is returned, and a specific error code may be retrieved by calling WSAGetLastError().

this is wrote in Winsock spec.  I cant understand when recv already receive all data, in eax go SOCKET_ERROR?
if not why?
if yes, why my loop not work?
:eek

Tedd

Short answer: you don't know.

It is for you and the sender to decide how this should be indicated.
If you know your data should end with a newline, then you can wait until you receive that newline, and then take that as the end of the data. Or, if you know the length of the message, then you can wait until you receive that number of bytes.
However, there is no way for anyone to know how much has actually been sent, except for the person sending it. And the only way they could tell you, is by sending that information to you (which is the same problem.)

Usually you receive your message with recv and if the message is not too big then you'll receive it all in one piece, so there will be no problem. If the message is bigger, then you need to find a way of knowing when you have received the ned of it :wink

(What are you using this for? Just for fun with small text messages, or a real protocol?)
No snowflake in an avalanche feels responsible.

LMZ

ok, i understand that i sould match when is the end of message,
i use HTTP, protocol,
thx to all

P1

Quote from: QvasiModo on August 22, 2005, 11:17:12 PM
Quote from: P1 on August 22, 2005, 02:05:53 PM
You need some winproc code to support the message pump.  Then call your recv proc.  Do not loop that code!  The message pump will notify you of new incoming socket data.

We need to clarify, all this is only valid when using asynchronous sockets.
Thank you QvasiModo.

Regards,  P1  :8)

P1

Quote from: LMZ on August 23, 2005, 11:38:48 AM
ok, i understand that i sould match when is the end of message,
i use HTTP, protocol,
thx to all
LMZ,
Are writing a Server or Client right now for the HTTP protocol?

Regards,  P1  :8)

QvasiModo

Quote from: LMZ on August 23, 2005, 11:38:48 AM
ok, i understand that i sould match when is the end of message,
i use HTTP, protocol,
thx to all

Usually you read up to 10 kb or so (it doesn't need to be 10k, it's just a good number  :toothy ), or until you find the two end-of-line markers at the end of the HTTP header. If somebody sends you an HTTP request (or response) that's bigger than your buffer size, you can report and error and close the socket.

For example, in a server, you would have a 10 kb buffer and call recv in a loop. If you find the two newlines, you've got the whole header. If not, keep reading until you hit the 10 kb limit. If you reach the limit and still haven't got the whole header, return a 400 Bad Request error and close the socket.

In a client, you read up to 10kb of response. If you can't find the two newlines, close the socket and report an error to the user. If you do, parse the response header and keep reading the data from the server until the connection is closed, or you have read all of it (use the Content-Length header to know how big the data is).

I hope my explanation wasn't too confusing (as they usually are!  :wink ). Feel free to ask any more questions. :U

LMZ

i write client,
i also think about Content-Length :P

bozo

I done a basic HTTP server/client once, from a client side, i relied on as LMZ says
"Content-Length:" header for allocation of data, but this could lead to errors from a malicious server..i know that is unlikely to happen, but think about it anyway.

i used ioctlsocket() with FIONREAD to determine how much data to get with recv() when running as a server.

LMZ

thx Kernel_Gaddafi
i will try to uze ioctlsocket()

QvasiModo

@Kernel_Gaddafi:

The problem with ioctlsocket is that if the TCP stream is sent in several packets, you might not get the correct size.

The fact is, in any case you must trust the other computer to know how much data you will have to read. Of course you have to validate your input, you can't allocate 2 GB in RAM just because the Content-Length told you so. :wink

@LMZ:

If you're writing a client, try using the WinINet library, or better yet, the WinHTTP library. They are both shipped with Windows and simplify the whole thing. (Then again you'll learn a lot more by doing things "the hard way"... you decide)

P1

There is even a browser in MASM available using the M$ control.  Use Search to find it.

Regards,  P1  :8)

bozo

Quote from: QvasiModo on August 24, 2005, 03:20:17 PM
@Kernel_Gaddafi:

The problem with ioctlsocket is that if the TCP stream is sent in several packets, you might not get the correct size.

I don't understand what you mean, ..but, if there is alternative method for checking size of data waiting to be read from socket, i would appreciate hearing about it.
I know of SELECT() but, what is the alternative you reccomend??

surely the operating systems tcp/ip driver would take care of how packets are buffered, not the API itself.

Quote
The fact is, in any case you must trust the other computer to know how much data you will have to read. Of course you have to validate your input, you can't allocate 2 GB in RAM just because the Content-Length told you so. :wink

I already acknowledged this fact in first post, and also mentioned that it is in unusual circumstances that such a server would behave this way.