🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Winsock recv help

Started by
7 comments, last by ziplux 23 years, 6 months ago
I'm trying to write a program using Winsock2 asyncronous (hope I spelled that right) sockets. When I run this code:
    
char sizebuffer;
char size[20];
int r = 0;
ZeroMemory(size, sizeof(size));	
ZeroMemory(&sizebuffer, sizeof(sizebuffer));

do
	{
	if( (r = recv (client,&sizebuffer,sizeof(sizebuffer),0)) == SOCKET_ERROR)  // get size

		{
		int e = WSAGetLastError();
		return 0;
		}
	else
		{
		strcat(size, &sizebuffer);
		i++;
		}
	} while(sizebuffer != '!');
    
in my FD_READ message, it should read one charater from the buffer until it hits a '!'. When I look at it in debug mode though, r, which is supposed to hold the number of bytes read, is 1 as it is supposed to be. But, sizebuffer has a bunch of extra characters on it, even though it is only 1 character, so when strcat is called, size get the character and about 4 characters of extra garbage. If I have it use size in recv and change the 1 to sizeof(size), then it readds all the characters. Is that problem that winsock can't read less than 4 or 5 bytes at a time? Help! Thanks in advance. My Geekcode: "GCS d s: a14 C++$ P+(++) L+ E-- W+++$ K- w++(+++) O---- M-- Y-- PGP- t X R- tv+ b++ DI+(+++) D- G e* h!" Decode my geekcode! Geekcode.com
Visit our web site: Asylum Entertainment Edited by - ziplux on 12/4/00 7:55:30 PM
My Geekcode: "GCS d s: a14 C++$ P+(++) L+ E-- W+++$ K- w++(+++) O---- M-- Y-- PGP- t XR- tv+ b++ DI+(+++) D- G e* h!"Decode my geekcode!Geekcode.com
Visit our web site:Asylum Entertainment
Advertisement

char chBuf;
char szBuf[20];
int r=0;
chBuf = 0;
ZeroMemory(szBuf, sizeof(szBuf));

for(int i=0; i < 20 && chBuf != '!'; i++)
{
if((r = recv(client, &chBuf, sizeof(chBuf), 0)) == SOCKET_ERROR)
{
...
}
szBuf = chBuf;<br>}<br></code><br><br>The above should work. But as a general rule, reading 1 byte of data per recv() is not a good idea. If you're going to do that, you might as well just use MSG_PEEK and get the whole thing, then do a recv without MSG_PEEK setting the length of the buffer to the length needed to read to the '!'. That would be faster. <br><br>Edited by - JonStelly on December 5, 2000 12:07:02 PM
Thanks for your reply. I''m at work right now so I can''t test it. If I can get your code working, I''ll try using MSG_PEEK.


My Geekcode: "GCS d s: a14 C++$ P+(++) L+ E-- W+++$ K- w++(+++) O---- M-- Y-- PGP- t X
R- tv+ b++ DI+(+++) D- G e* h!"
Decode my geekcode!
Geekcode.com


Visit our web site:
Asylum Entertainment
My Geekcode: "GCS d s: a14 C++$ P+(++) L+ E-- W+++$ K- w++(+++) O---- M-- Y-- PGP- t XR- tv+ b++ DI+(+++) D- G e* h!"Decode my geekcode!Geekcode.com
Visit our web site:Asylum Entertainment
I tried the code you posted, and it worked. But I still have a problem. Here is my FD_READ message:
  case FD_READ:	{	DWORD dwSize = 0;	int r = 0;	char chBuf;	char szBuf[20];	char *szRecvBuf = NULL;	chBuf = 0;	ZeroMemory(szBuf, sizeof(szBuf));	for(int i=0; i < 20 && chBuf != ''!''; i++)	{	if((r = recv(client, &chBuf, sizeof(chBuf), 0)) == SOCKET_ERROR)	{		// error	}		szBuf [ i ] = chBuf;	}	szBuf [strlen(szBuf)-1] = NULL;	dwSize = atoi(szBuf);	szRecvBuf = new char[dwSize+1];		if(szRecvBuf == NULL)	{	// error	return(1);	}	ZeroMemory(szRecvBuf, sizeof(szRecvBuf));	recv(client, szRecvBuf, sizeof(szRecvBuf), 0);			SendMessage(ChatBox, WM_SETTEXT, 0, (LPARAM)szRecvBuf);	delete[] szRecvBuf;	} break;  

Everything up to the delete[] command works. When I single-step through it, I find that when the delete command is executed, the program goes back to the DWORD dwSize = 0; line for some reason, and the following errors are printed in the debug output area:
memory check error at 0x00AB0EA2 = 0x00, should be 0xFD.memory check error at 0x00AB0EA3 = 0x00, should be 0xFD. 

Any thoughts? Thanks in advance.


My Geekcode: "GCS d s: a14 C++$ P+(++) L+ E-- W+++$ K- w++(+++) O---- M-- Y-- PGP- t X
R- tv+ b++ DI+(+++) D- G e* h!"
Decode my geekcode!
Geekcode.com


Visit our web site:
Asylum Entertainment
My Geekcode: "GCS d s: a14 C++$ P+(++) L+ E-- W+++$ K- w++(+++) O---- M-- Y-- PGP- t XR- tv+ b++ DI+(+++) D- G e* h!"Decode my geekcode!Geekcode.com
Visit our web site:Asylum Entertainment
Close the project, exit VS6, delete the debug directory, do a full re-build.

That may fix a jmp to the dword...=0

The
memory check error at 0x00AB0EA2 = 0x00, should be 0xFD.memory check error at 0x00AB0EA3 = 0x00, should be 0xFD
means that you overflowed past the end of your allocated memory. MSVC, in debug mode, seems to pad all your data with FD''s for some bytes past their allocated area and checks to make sure they''re still FD when you delete.

The error is not with the delete[], it just isn''t detected util then.

Happy Debugging!

Magmai Kai Holmlor
- The disgruntled & disillusioned
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
szBuf [strlen(szBuf)-1] = NULL;

Think about what that''s doing real quick. How does the strlen() function determine string length? By scanning forward looking for the null terminator. If that character is null, why do you need to set it again? You''ve already called ZeroMemory(..), so all characters are null that you haven''t set after the ZeroMemory().


I can see what you''re trying to do now, so I have a question. Why don''t you just send the length of the message as an integer, instead of a string? It would be much simpler, no need to parse character by character or convert strings to integer in your recv function.
quote: Original post by JonStelly

szBuf [strlen(szBuf)-1] = NULL;

Think about what that''s doing real quick. How does the strlen() function determine string length? By scanning forward looking for the null terminator. If that character is null, why do you need to set it again? You''ve already called ZeroMemory(..), so all characters are null that you haven''t set after the ZeroMemory().


I can see what you''re trying to do now, so I have a question. Why don''t you just send the length of the message as an integer, instead of a string? It would be much simpler, no need to parse character by character or convert strings to integer in your recv function.


That line gets rid of the trailing ''!''. I could send it as an integer...I''ll have to try that. I might even use a system of tagging and send the entire contens of a struct as my messages instead. But, I''m still having problems with this. It works fine now, but after it gets the message, FD_READ is called 2 extra times and recv returns WSAEWOULDBLOCK each time. Is this normal? I just return(1) from my function and it works fine, but I don''t know why this is happening.



My Geekcode: "GCS d s: a14 C++$ P+(++) L+ E-- W+++$ K- w++(+++) O---- M-- Y-- PGP- t X
R- tv+ b++ DI+(+++) D- G e* h!"
Decode my geekcode!
Geekcode.com


Visit our web site:
Asylum Entertainment
My Geekcode: "GCS d s: a14 C++$ P+(++) L+ E-- W+++$ K- w++(+++) O---- M-- Y-- PGP- t XR- tv+ b++ DI+(+++) D- G e* h!"Decode my geekcode!Geekcode.com
Visit our web site:Asylum Entertainment
Ahh, I got ya, just completely missed the ''-1''.

And sending the data as a structure is my prefered method too.
If it helps you
  enum PacketType	{	PT_EMPTY        = 0x0000,	PT_CHAT         = 0x0001,	PT_LOGIN        = 0x0002,	PT_PING         = 0x0003,	PT_PONG         = 0x0004,	PT_PLAYER       = 0x0005,	PT_FORCEDWORD   = 0xFFFFFFFF	};class CPacket	{	public:		CPacket();		~CPacket();		//friend class CRecvSocket;		//friend class CNetworkClient;		void Chat(const CString&);		//void Player(const CPlayer&);		void Player(const CPlayer&);		void Pack(const void*, long);				void Serialize(CArchive& ar);		friend CArchive& operator<<(CArchive& arc, const CPacket& packet);		friend CArchive& operator>>(CArchive& arc, CPacket& packet);				const PacketType& GetPacketType()			{			return(packettype);			}	//protected:		DWORD GenerateSerial(DWORD);		DWORD GenerateECC();	//private:		long length;		PacketType packettype;		DWORD serialnum;		DWORD ecc;		char* data;			};  

that''s what my packet looks like - though you can drop the size DWORD entirely if you are using UDP.

Magmai Kai Holmlor
- The disgruntled & disillusioned
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara

This topic is closed to new replies.

Advertisement