The MASM Forum Archive 2004 to 2012

General Forums => The Workshop => Topic started by: LMZ on August 22, 2005, 06:52:22 AM

Title: recv in loop
Post by: LMZ on August 22, 2005, 06:52:22 AM
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
Title: Re: recv in loop
Post by: 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.

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)
Title: Re: recv in loop
Post by: 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.
Title: Re: recv in loop
Post by: LMZ on August 23, 2005, 08:00:51 AM
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
Title: Re: recv in loop
Post by: Tedd on August 23, 2005, 09:17:51 AM
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?)
Title: Re: recv in loop
Post by: 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
Title: Re: recv in loop
Post by: P1 on August 23, 2005, 01:35:49 PM
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)
Title: Re: recv in loop
Post by: P1 on August 23, 2005, 01:44:46 PM
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)
Title: Re: recv in loop
Post by: QvasiModo on August 23, 2005, 03:31:21 PM
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
Title: Re: recv in loop
Post by: LMZ on August 24, 2005, 06:26:14 AM
i write client,
i also think about Content-Length :P
Title: Re: recv in loop
Post by: bozo on August 24, 2005, 07:03:18 AM
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.
Title: Re: recv in loop
Post by: LMZ on August 24, 2005, 01:15:12 PM
thx Kernel_Gaddafi
i will try to uze ioctlsocket()
Title: Re: recv in loop
Post by: 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.

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)
Title: Re: recv in loop
Post by: P1 on August 24, 2005, 03:22:45 PM
There is even a browser in MASM available using the M$ control.  Use Search to find it.

Regards,  P1  :8)
Title: Re: recv in loop
Post by: bozo on August 25, 2005, 12:11:31 AM
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.
Title: Re: recv in loop
Post by: LMZ on August 25, 2005, 10:58:10 AM
i think that learn winsock is most useful for me,
because i can port than more simply my programs in bsd (i think :))

but i'll will read about http windows functions, thx
Title: Re: recv in loop
Post by: QvasiModo on August 29, 2005, 04:14:15 PM
Quote from: Kernel_Gaddafi on August 25, 2005, 12:11:31 AM
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??
I'm afraid there is no method at all... not a 100% reliable one that is. The application at the other endpoint of the TCP connection has to tell you how many bytes to expect. You should be able to handle the cases when it's sent too much or too little.

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

I know, but that's not what I mean. It's just that you might not get the whole reply from the web server in a single recv() call, and  ioctlsocket will only tell you how much you can read in the next call (not how much has the server truly sent).

Quote
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.

I was only pointing out that the only validation worth making with ioctlsocket is to allocate a read buffer, not to replace the Content-Length header altogether.

And you're absolutely right that it would be unusual, tipically you get the whole thing in just one recv() call. I'm being picky that's all. :)
Title: Re: recv in loop
Post by: P1 on August 29, 2005, 04:53:04 PM
Quote from: QvasiModo on August 29, 2005, 04:14:15 PM
I'm being picky that's all. :)
I would not call that 'picky'.  Your just trying to get him to realize the consequences of the circumstances he is expect to program to. 

Then there is the hackers who send crafted headers to crash your software.

Welcome to Internet Programming Realities 101 !!!   :dance:

Regards,  P1  :8)
Title: Re: recv in loop
Post by: James Ladd on August 29, 2005, 08:47:11 PM
You could also check out FASt Server here: www.jamesladdcode.com
It uses overlapped socket IO which is very fast indeed.
rgs, James (striker).
Title: Re: recv in loop
Post by: bozo on September 02, 2005, 12:45:03 PM
QuoteI'm afraid there is no method at all... not a 100% reliable one that is. The application at the other endpoint of the TCP connection has to tell you how many bytes to expect. You should be able to handle the cases when it's sent too much or too little.

I don't mean to offend you, but this is a nonsensical statement.
Unless a server were processing RAW packets, ioctlsocket() should not "miss" anything at all, as it is the underlying TCP/IP driver which buffers the "unread" data from the socket..

Do you mean, processing RAW packets? that there is no reliable way?
Fair enough, I don't know.

Using ioctlsocket with FIONREAD simply peeks at the socket buffer, to see if anything is there, and returns the size of the buffer (if anything, else return zero), thats my understanding of it.

I'm not that experienced with TCP/IP, but what you say just doesn't make any sense.
And you say there is not 100% reliable way..

To me, that would mean TCP/IP is broken and unreliable, which you and I know is not 100% accurate.

As TCP/IP stack of Windows 2000 and upwards is based on FreeBSD code, I would say its pretty reliable.
Title: Re: recv in loop
Post by: QvasiModo on September 02, 2005, 02:57:01 PM
We're talking of two different things. I seem to be having a problem to express myself this days, my apologies. :(

I didn't mean to use raw packets at all. I never meant to say TCP was unreliable. I don't imply that ioctlsocket fails to reckong how many bytes there are in the buffer. You are absolutely right.

What I mean that there is no way to know in advance how many bytes will the whole stream take. You can only know how many are ready to be obtained in the next recv() call. That's why you need to use the Content-Length header when processing HTTP streams, you can't expect to know the size of the whole stream, just how much has been buffered already by the TCP/IP stack. HTTP clients and servers can't be reliably implemented if they ignore the Content-Length header.

Hope I've made myself clear this time, I don't want to confuse LMZ  :toothy

PS: Whenever you see I stop making sense, don't hesitate to tell me so. I won't get offended for being corrected. :wink