🎉 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!

Sending variable sized string via Winsock

Started by
3 comments, last by ziplux 23 years, 6 months ago
I''d like to send a variable-sized string via Winsock. Here''s what I''ve got so far:
  
// Data structures used

class MSG_GENERIC
	{
	public:
		MSG_GENERIC()
			{

			}
		DWORD type;
	};

class MSG_STRING : public MSG_GENERIC
	{
	public:
		MSG_STRING()
			{
			textsize = 0;
			text = NULL;
			type = WCS_MESSAGE;
			}
		DWORD textsize;
		char *text;
	};
...
//

// Here''s the function that sends a message of type MSG_STRING.  EditBox is an edit box control.  ChatBox is a read-only edit control

//

MSG_STRING str;
DWORD dwSize = 0;
char *szSendBuff = NULL;

int l = SendMessage(EditBox, WM_GETTEXTLENGTH, 0,0);
str.text = new char[l+1];
	SendMessage(EditBox, WM_GETTEXT, l+1, (LPARAM)str.text);
str.textsize = l+1;

dwSize = sizeof(str)+str.textsize;
szSendBuff = new char[dwSize+sizeof(dwSize)];
ZeroMemory(szSendBuff, dwSize+sizeof(dwSize));
memcpy(szSendBuff, (char*)&dwSize, sizeof(dwSize));
memcpy(szSendBuff+sizeof(dwSize), (char*)&str, dwSize);

// this code prints the text to the chat area as a test.  It doesn''t send anything.  This works fine.

char *data = szSendBuff+sizeof(dwSize);
MSG_GENERIC *msg = (MSG_GENERIC*)data;
switch( msg->type )
	{
	case WCS_MESSAGE:
		{
		MSG_STRING *temp;
		temp = (MSG_STRING*)data;
		SendMessage(ChatBox, WM_SETTEXT, 0, (LPARAM)temp->text);
		} break;
	}
//

// This next line sends the structure.  I would comment out the above if I were to use this line.

// This does not give an error, but watch what happens in the recv function...

int e = send(outgoing.s, szSendBuff, dwSize+sizeof(dwSize), 0);
// cleanup

delete[] str.text;
delete[] szSendBuff;
...
// In my FD_READ message...my recv funciton.  s is a valid socket with data to be recved

DWORD dwSize = 0;
int r = 0;
char *szRecvBuf = NULL;
// get size of data to be recieved

if((r = recv(s, (char*)&dwSize, sizeof(dwSize), 0)) == SOCKET_ERROR)
	return(1);
// create buffer to hold data

szRecvBuf = new char[dwSize];

ZeroMemory(szRecvBuf, dwSize);
// get data

recv(s, szRecvBuf, dwSize, 0);
// pass data to handling function

HandleMessage(szRecvBuf);

delete[] szRecvBuf;

return(0);
//

// My HandleMessage funciton...here come the error.  data is the buffer from the FD_READ message

MSG_GENERIC *msg = (MSG_GENERIC*)data;
// switch on the type.  this works fine

switch( msg->type )
	{
	case WCS_MESSAGE:
		{
		// it finds it to be a MESSAGE

		MSG_STRING *temp;
		temp = (MSG_STRING*)data; // cast to correct type

		// now, temp->text should contain the text....but it does not

		// when I look in the Chat area, I either see ''i'' or some other kind of garbage when I set the text of it equal to temp->text

		SendMessage(ChatBox, WM_SETTEXT, 0, (LPARAM)temp->text);
		} break;
	}
return(0);
  
I assume that I am sending the address of the text rather than the actual text. So, how do I accomplish this? What do I have to do to be able to send variable length strings? Thanks in advance, and sorry for the long post. 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
Advertisement
You need to copy the string along with the other stuff into a buffer and send the whole thing.

  		arc << packet.length;		arc << (long)packet.packettype;		arc << packet.serialnum;		int n = packet.length - sizeof(CPacket) + sizeof(packet.data);		for(int i=0;i<n;i++)			arc << packet.data<i>;		arc << packet.ecc;  

Just try to tell C++ isn''t better at this :p
Those << are basically memcpy() replacements, that know what to do with each type of data. Is this case the .data property is a void* and the chat string has already been copied to it, and the lenght of the string has been set in the .length property. (sizeof(packet.data) is always 4)

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
Here''s just a really quick example of how I handle variable length strings:



#define MSG_TYPE_SAY 0x0001
#define MAX_SAY_LEN 512

typedef struct NET_MSG
{
DWORD Type;
virtual DWORD Size()
{
return sizeof(NET_MSG);
}
}*PNET_MSG;

typedef struct NET_MSG_SAY : NET_MSG
{
char Text[MAX_SAY_LEN];
virtual DWORD Size()
{
return sizeof(NET_MSG) + strlen(Text) + 1;
}
}*PNET_MSG_SAY;


In my send function, I send the structure, but I call the Size() function from my send() function and only send that many bytes. So the NET_MSG_SAY structure should be 516 bytes, but if the string being sent is only 20 characters, the Size() function would only return 25, so it would only send that many bytes. On the receiving side, you cast first to PNET_MSG, then switch on the messages Type to figure out what kind of message you have.

Hope that helps at least a little.
quote: Original post by JonStelly

Here''s just a really quick example of how I handle variable length strings:



#define MSG_TYPE_SAY 0x0001
#define MAX_SAY_LEN 512

typedef struct NET_MSG
{
DWORD Type;
virtual DWORD Size()
{
return sizeof(NET_MSG);
}
}*PNET_MSG;

typedef struct NET_MSG_SAY : NET_MSG
{
char Text[MAX_SAY_LEN];
virtual DWORD Size()
{
return sizeof(NET_MSG) + strlen(Text) + 1;
}
}*PNET_MSG_SAY;


In my send function, I send the structure, but I call the Size() function from my send() function and only send that many bytes. So the NET_MSG_SAY structure should be 516 bytes, but if the string being sent is only 20 characters, the Size() function would only return 25, so it would only send that many bytes. On the receiving side, you cast first to PNET_MSG, then switch on the messages Type to figure out what kind of message you have.

Hope that helps at least a little.


Good idea, nice and simple. Thanks. I''ll try it tomorrow when I have time.



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
Ok, the text sending part worked fine. But when I tried to add a char username[20] to my class, the username doesn't get copied to the buffer. Is this because I truncate the class? Here's my class:
    class MSG_STRING : public MSG_GENERIC	{	public:		MSG_STRING()			{			type = WCS_MESSAGE;			ZeroMemory(text, MAX_STRING_LEN);			ZeroMemory(name, MAX_USERNAME_LEN);			}		virtual DWORD size()			{			return sizeof(MSG_GENERIC) + strlen(text) + 1 + strlen(name) + 1;			}		char text[MAX_STRING_LEN];		char name[MAX_USERNAME_LEN];	};    

When it is copied to the buffer, it doesn't take the username with it. Is this even possible? Thanks for all your help so far!


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 December 8, 2000 10:53:28 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

This topic is closed to new replies.

Advertisement