views:

110

answers:

3

I need a little help if someone's got a minute. I've written a web server using IO completion ports, but I am having some trouble sending out large files. Web pages seem to load fine, but during large file transfers, WSASend() fails after a few minutes with error "The specified network name is no longer available."

Right now, my server just closes the associated connection when any overlapped operation fails. Is this the right thing to do? or should I retry failed overlapped operations a few times before I close the socket? I am using tcp/stream sockets.

(fixed) I am also receiving what seems like random 0 byte packets from WSARecv. I am not sure what to make of this, or if the problem is related.(/fixed)

Thanks for any help

edit: now that the server properly handles connections, and has a much more comprehensive log, it seems like Len is right. The client is closing the connection for some reason.

The log:

Initializing Windows Sockets...
Forwarding port 80...
Starting server...
Waiting for incoming connections...
Socket 1128: Client connected.
Socket 1128: Request received
Socket 1128: Sent response
Socket 1128: Error 64: SendChunk() failed. //WSASend()
Socket 1128: Closing connection - GetQueueCompletionStatus == FALSE

so the question is now, why would the client close the connection? It takes anywhere from 2-5 minutes to happen. I have decreased the buffer size to 4098 bytes per send, and only send the next chunk when the first has completed.

Thanks again for any ideas on this.

p.s. I even just implemented a retry function so that it will retry a failed overlapped IO operation five times before giving up....still no luck =(

+4  A: 

A zero length packet returned from recv indicates client on the other end has closed the connection.
Which answers why your subsequent send to the client failed.

http://www.opengroup.org/onlinepubs/009695399/functions/recv.html

If no messages are available to be received and the peer has performed an orderly shutdown, recv() shall return 0.

YeenFei
Thanks for clearing that up. I don't think this is the problem though. I added some details to the original message.
Nick
+1  A: 

Are you doing anything to impose some form of flow control on your data transmission?

If not then you are probably using up resources which is causing the send to fail.

For example, if you are simply issuing LOTS of WSASend() calls one after the other rather than pacing them based on when they complete then each one will use system resources (non-paged pool and/or lock pages which go towards the 'locked pages limit'). You'll then likely eventually fail with ENOBUFS or similar errors.

What you need to do is build a flow control system that works off of the send completions so that you only ever have a known number of sends outstanding at a time.

See these questions for more detail:

http://stackoverflow.com/questions/3080328/implement-a-good-performing-to-send-queue-with-tcp/3086025#3086025

http://stackoverflow.com/questions/3034047/limiting-tcp-sends-with-a-to-be-sent-queue-and-other-design-issues/3036531#3036531

Len Holgate
thanks, but I don't think that's it. I was only testing it with one transfer. When the server receives the http header, it sends the response header. On completion of that, is sends the first chunk, then sends the next chunk(8192 bytes) when the first completes, and so on. I'll take a look at the pages that you recommended anyways.
Nick
on the other hand, this server works fine if I connect with the browser on the same computer, and averages a download speed of 20-30 MB/s without any error.
Nick
So you ARE only sending the next when the first send completion occurs? That should be fine. What error does your send completion fail with? With a real network connection between you you'll likely see TCP flow control kicking in which will slow your send completions and if you're not pacing your sends based on send completions you'll queue lots of data locally in the TCP stack ...
Len Holgate
But then the error is not ENOBUFS. GetQueuedCompletionStatus returns false, and then GetLastError returns 64, or "The specified network name is no longer available"
Nick
In which case the client is likely closing the connection... Get a network trace using WireShark.
Len Holgate
You know what? I added a more comprehensive log output, and found the server doing different things whether I connected with IE or Firefox. IE didn't seem to post any 0 byte recvs at all..not sure why. The last version of this server didn't even handle persistent connections, so I'll have to go over the connection handling and make sure its done fully and correctly. Thanks for the help =)
Nick
I have used wireshark once before, but I don't understand how it would help. The original question was updated^
Nick
But now you can see what's happening between client and server. So you know if the client is closing the connection and you know when. You can then reason on why it's doing that.
Len Holgate
I don't understand how I could really reason any further at this point. I have made sure that the server is working correctly now, and the server writes all relevant events to the log. I am sure now, that for some reason, the browser(IE and Firefox) both eventually terminate the connection with an abortive close. If I am sending the packets sequentially, and only upon completion, I really don't understand what else it could be =/
Nick
I would need to somehow monitor the browser's socket, and find out what the error code is when the connection terminates...can Wire Shark do that?
Nick
omg......xitami web server does it too. something must be wrong with the internet, or my computer
Nick
A: 

Finally figured it out.

from Rogers Internet Terms of Service:

Without limitation, you may not use (or allow anyone else to use) our Services to:

(xvi) operate a server in connection with the Services, including, without limitation, >mail, news, file, gopher, telnet, chat, Web, or host configuration servers, multimedia >streamers or multi-user interactive forums;

how lame is that? O_o

good news: server works fine =)

edit- called Rogers. They verified that they are cutting me off, and told me that I need a business account to run a web server.

Nick