i'm stuck... please help! i'm using blocking mode /w many threads to take HTTP requests... so if i do something like:

GET / HTTP/1.1

using TELNET with a blank line after, the program will work and respond... it seems to send a response (using a debugger to trace my code - and checking for errors and amount of data sent) when i use a web browser, but Netscape 4.7, 6.0 and 7.0PP1 all just have their respective icons spinning... and then time out or something. i've closed the connection, too... my procedure looks something like this:

accept socket
@@:
recv data
process data
unless blank line, jmp @@
send something like "<html><body>blah</body></html>",0dh,0ah,0
close socket

i even tried looking at an example server and i couldn't figure out what i'm doing wrong... and i tried dissecting my web server that i wrote in VB (yes, boo, i know)...

if you want, i can send the asm source here, too. this is just something i'm doing for fun :)
Posted on 2002-06-12 22:20:42 by jademtech
Source would help.

I don't know the requirements off hand, but:

1) Are you sending the HTTP header?
2) When you accept a new socket, are you sending the data to it, or out port 80?
Posted on 2002-06-13 00:33:04 by eet_1024
Hi!

eet_1024 is correct.
Seems like you forgot the HTTP header.
Look in my posting "HTTP header problems" for some examples or look in your RFC.

You must at least return the following:



HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 12345
; CRLF here
; CRLF here
<html>
blah
</html


Where Content-Length is the size of the HTML data you send to the Browser.
Posted on 2002-06-13 00:39:42 by bazik
hm... thanks for the replies... the other two servers (my own + the one from Icz's site) both do not sent content length and they work fine. neither do other web servers that i TELNET into...

i tried sending headers... and it works... hmmm... wonder why the other programs worked /wo sending headers?
Posted on 2002-06-13 08:19:40 by jademtech
They have to send headers, or the browser won't understand them. You can skip Content-Length and the page will work with all browsers, it's just not very nice :)
In ASP, if you turn buffering off, it won't set Content-Length either so I guess it's OK to skip it.
Posted on 2002-06-13 09:50:12 by Qweerdy
Could you post your code? I would like to see what you are doing?

Later,
gorshing
Posted on 2002-06-13 10:06:44 by gorshing
Problem is that when you don't send the content-length, the size must be determined by something else. Normally the connection is shut down when the file is finished. However this is inefficient, if the content-lenght *is* given, the connection doesn't have to be closed (well at least when the connection header is set to 'keep-alive') and more requests can be done using the same connection (HTTP 1.1 also allows to pipeline requests, i.e. sending multiple requests even when the first response isn't finished yet).
Alternatively, a transfer encoding can be applied to specify the data length. The 'chunked' transfer encoding for example, splits the response in blocks and first transfers the bytesize of each block. This way the content-length doesn't have to be given beforehand but the connection doesn't have to be closed either.

Thomas
Posted on 2002-06-13 10:08:08 by Thomas
hopefully i've attached enough to assemble...

sorry - i have a terrible coding "style" and it's not optimised yet... so...
Posted on 2002-06-13 10:40:22 by jademtech
oh yeah - i also added a send and a ret near the beginning of the part that sends the response, in case anyone downloads the program - so right now the response function will *always* return the same thing, as long as a valid GET request is posted.

should also read:
invoke send,hSocket,addr HTTPHead,LENGTHOF HTTPHead-1,0

instead of
invoke send,hSocket,addr HTTPHead,LENGTHOF HTTPHead,0


and the program binds to port 88 by default (i'm running a web server on port 80)
Posted on 2002-06-13 10:41:47 by jademtech
sorry... i have another question...


invoke wsprintf,addr ErrorMessageBuffer,addr GenericHead,404,addr FileNotFound,LENGTHOF FileNotFoundBody
invoke lstrlen,addr ErrorMessageBuffer
mov OutputSize,eax
invoke send,hSocket,addr ErrorMessageBuffer,OutputSize,0
invoke send,hSocket,addr FileNotFoundBody,LENGTHOF FileNotFoundBody-1,0
ret


unless i put a Sleep,1 before the ret, the second send function doesn't send stuff... i'm assuming Sleep,1 only works because i have no lag connecting to myself, though... am i to poll for status? i can not figure out how to use "select" if that is what is to be used... thanks.
Posted on 2002-06-13 13:08:09 by jademtech
After the function has returned I guese your calling closesocket wich means the socket will close before the data has been sent.
with setsockopt there is the SO_LINGER option wich waits for all unsent data to be sent before sending
Posted on 2002-06-13 15:07:55 by Kudos
Kudos to Kudos! thnx... i'm trying it out, now...
Posted on 2002-06-13 15:30:12 by jademtech
Hmm.. if you are using blocking mode sockets the send call should block until all bytes are sent, so there should be no need for a wait function :confused:..

Thomas
Posted on 2002-06-13 16:10:30 by Thomas
am i using blocking mode? i'm not sure - i thought i was, then i realised i used a WSAAsyncSelect thinggy... (i'm an utter n00b to winsock /w ASM)



... (two lines of code that send data)
mov l_struct.l_onoff,1
mov l_struct.l_linger,100
invoke setsockopt,hSocket,SOL_SOCKET,SO_LINGER, addr l_struct, SIZEOF l_struct
mov pBuffer,SIZEOF l_struct
mov l_struct.l_onoff,0
invoke getsockopt,hSocket,SOL_SOCKET,SO_LINGER, addr l_struct, addr pBuffer
.if l_struct.l_onoff==1
invoke MessageBeep,MB_ICONEXCLAMATION
.endif
invoke closesocket,hSocket


so now i've used SO_LINGER /w non-zero values for both of the linger structure's elements... but it still only sends the data from the first send request... no muffin for me.


If SO_LINGER is set with a nonzero time-out interval on a blocking socket, the closesocket call blocks on a blocking socket until the remaining data has been sent or until the time-out expires. This is called a graceful disconnect. If the time-out expires before all data has been sent, the Windows Sockets implementation terminates the connection before closesocket returns.
Posted on 2002-06-13 17:28:06 by jademtech
WSAAsyncSelect will have set any socket it was used ont o noneblocking mode, so the SO_LINGER meathod won't work. If you want to use WSAAsyncSelect then maybe this will help

To assure that all data is sent and received on a connected socket before it is closed, an application should use shutdown to close connection before calling closesocket. For example, to initiate a graceful disconnect:

Call WSAAsyncSelect to register for FD_CLOSE notification.
Call shutdown with how=SD_SEND.
When FD_CLOSE received, call recv until zero returned, or SOCKET_ERROR.
Call closesocket
Posted on 2002-06-13 17:44:46 by Kudos
thnx... i read that already, though... unfortunately, i don't know how to pass the socket handle back to the main window function that processes windows messages... or is that passed back in lParam or wParam or something else? sorry if that is badly worded.
Posted on 2002-06-13 17:47:43 by jademtech
hmm
I'm not sure how to get the socket into the main window proc (anyone know?) but maybe you could do something like this.
When you set up WSAAsyncSelect use the thread ID of the thread that wants to close a socket then when your window proc receives that message it uses PostThreadMessage to tell the thread it is OK to call closesocket.
Posted on 2002-06-13 19:17:04 by Kudos
aha!


invoke shutdown,hSocket,1


i got my code to work! thanks for all the help Kudos! it turns out that i can use shutdown after all!

here is my code:



...(send stuff)
invoke shutdown,hSocket,1
invoke closesocket,hSocket
ret


is the MSDN documentation is wrong?


If the how parameter is SD_SEND, subsequent calls to the send function are disallowed. For TCP sockets, a FIN will be sent after all data is sent and acknowledged by the receiver.


and using the include winsock 2 include file for VC, i found the following:
SD_RECEIVE=0x00
SD_SEND=0x01
SD_BOTH=0x02

However, the program worked when i used "sd_send" (i.e. my transmission continued, not accepting new data), but not when i used 0 or 2.
Posted on 2002-06-13 20:58:12 by jademtech
thats much cleaner then relying on windows to send a message after shutdown has been called.
Posted on 2002-06-13 21:12:46 by Kudos