Archived

This topic is now archived and is closed to further replies.

WSARecv Problems.

This topic is 5810 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey all, I've written a IOCP server for my game, and it works great in debug mode. However, when I recompile in release mode, the recv code stops working :-(. The recive thread code is below. Can someone show me what I'm doing wrong, and why changing to release mode messed it up?
  
UINT HandleIncoming(LPVOID pParam)
{

	WSAOVERLAPPED overlap[MAXCLIENTS];
	for(int q=0;q<MAXCLIENTS;q++)
	{
	::memset( &overlap[q], 0, sizeof( overlap[q]) );
	}
	do{
		if(recive==true)
		{
		for(int i=0;i<currentopensocket;i++)
		{
			DWORD bytesread;
			buffer.buf=info[i].postionofship;
			buffer.len=sizeof(info[i].postionofship);
			WSARecv(ServerSocket[i].Socket,&buffer,1,&bytesread,&flags,&overlap[i],NULL);
			ServerSocketState[i]=recving;

		}
		recive=false;
		}
	}while(1==1);
	return 1;
}



 

  
Thanks, Jesse www.laeuchli.com/jesse/ [edit: replaced cpp tags with source tags] Edited by - Magmai Kai Holmlor on January 13, 2002 8:52:37 PM

Share this post


Link to post
Share on other sites
Maybe try posting your code in a [source ][/source ] tag so that it is readable... (remove the space at the end of ''source '' in the tag example above).


-Brannon

Share this post


Link to post
Share on other sites
That works in a debug build?!

For starters, I''m pretty sure you need to check the return code from WSARecv - it could complete immedietly - if it doesn''t it''ll return an erro and WSAGetError will return WASEWOULDBLOCK. In this case you need to hang on the event in the overlapped structure - which you never create (another problem).

Did you create the socket with the WSA_FLAG_OVERLAPPED flag? Or do you _want a blocking operation? If that''s the case, you don''t pass an overlapped structure into WSARecv - you pass NULL. Again you need to check the error code, because it will return with an error when the socket is closed or when WSACleanup is called, in which case you don''t want to process the data in the buffer.

Share this post


Link to post
Share on other sites
No, he''s passing a valid overlapped structure. The final param to WSARecv is the completion routine (which you don''t want if you''re using IOCPs).

One thing you should probably do is derive your own WSAOVERLAPPED structure.. something like:

  
typedef struct
{
WSAOVERLAPPED Overlapped;
DWORD BytesRead;
BYTE* Buffer;
DWORD BufferSize;
DWORD Flags;
} MYOVERLAPPED;


And cast that to a (WSAOVERLAPPED*) when calling WSARecv() (or pass &my_overlapped.Overalapped, which ever looks cleaner to you... they both do the same).

For things like BytesRead, you need to keep the storage for that valid until the recv actually completes, be it immediately, or in the IOCP thread. Try keeping a pool of overlapped structures that you get one from when calling WSARecv, and return one to when the recv completes. Also, even if the recv completes immediately, the notification will still be posted to the IOCP, so just handle it there (unless you want to deal with ignore dup notifications... I had to learn this one the hard way...).

Other than that, you should definitely be checking the result of WSARecv(). That might give you an indication of what is failing. Maybe you are getting ERROR_INVALID_PARAM (or the WSA equivalent) in release, but you wouldn''t know.



-Brannon

Share this post


Link to post
Share on other sites
quote:

For things like BytesRead, you need to keep the storage for that valid until the recv actually completes, be it immediately, or in the IOCP thread.



If you are referring to the lpNumberOfBytesRecvd parameter passed to WSARecv, you are incorrect. When using Overlapped I/O and WSARecv doesn''t complete immediately (i.e. GetLastError() returns WSA_IO_PENDING), lpNumberOfBytesRecvd does not get used. lpNumberOfBytesRecvd only gets updated if WSARecv completes immediately.

You determine the number of bytes transferred by using the cbTransferred parameter of GetQueuedCompletionStatus.



Dire Wolf
www.digitalfiends.com

Share this post


Link to post
Share on other sites
If it''s not retained, then I don''t think you''d have any way of getting the MSG_PARTIAL (or whatever) value... not that UDP or TCP support partial messages .. but some other protocols do.


-Brannon

Share this post


Link to post
Share on other sites
Er, he never creates an event to use for overlapped IO, nor creates a completion port, nor creates a completion port and an event, nor gives it a completion routine... so I don''t see how it would ever work... _unless it''s a blocking socket.

Overlapped IO functions doesn''t always return WSAEWOULDBLOCK, they will will return S_OK/NOERROR if data is already queued when you issue a request (I had a nasty bug in my CComPort class for ignoring this case). In which case you need that cBytesRecv, otherwise I think it''s garbage.

Share this post


Link to post
Share on other sites
He states that he created an IOCP server, so I am assuming that somewhere he sets up the IOCP.

laeuchli- you are setting up the socket and IOCP correctly right? If you still can''t get this to work, maybe you should post your IOCP thread function, and snippets from how you create your sockets and the IOCP.


-Brannon

Share this post


Link to post
Share on other sites
quote:

Er, he never creates an event to use for overlapped I/O, nor creates a completion port, nor creates a completion port and an event, nor gives it a completion routine... so I don''t see how it would ever work... _unless it''s a blocking socket.



You sound in a bad mood lately Mag...work getting to you or something?

Just thought I''d point out that when using overlapped I/O with I/O completion ports, you don''t create an event. I think you are mixing up WSAWaitForMultipleEvents/WSAGetOverlappedResult with I/O completion ports. Also, you don''t create an event in the OVERLAPPED data structure when using completion callbacks. The hEvent parameter is ignore when you request a callback.

Lastly, I would also assume that he created the I/O completion port object in another section of code.

When a program works in debug mode but not in release it is usually some stupid memory bug like a buffer overflow. For instance, I once had a buffer and a socket variable (int) stored closely together in memory. I was writing past my buffer and into my socket variable''s memory space which ended up changing the socket handle number. This obviously caused remaining calls to fail with "Not a socket." This didn''t show in debug because I had extra padding added after each variable to test for overwrites (custom memory management.) So even though the bug occurred in debug, it didn''t overwrite anything because of the padding. At least the custom memory manager caught it.

Dire Wolf
www.digitalfiends.com

Share this post


Link to post
Share on other sites