Advertisement

Send/Recv Error

Started by May 20, 2002 04:37 PM
9 comments, last by 1kevgriff 22 years, 8 months ago
I''m trying to write a winsock wrapper, and I''m good so far up to my send and receive class functions. I''m trying to be able to send any type of data I can via these functions. Here is the code:
  
int CNetwork::Send(void *buffer, int bufLen)
{
	char *data = NULL;

	data = new char[bufLen];
	memcpy(data, buffer, bufLen);

	if (send(socketInfo, data, bufLen, NULL) != 0)
	{
		if (debug == true)
			ProcessError(WSAGetLastError());
		return 1;
	}
	else
		return 0;
}

int CNetwork::Receive(void *buffer, int bufLen)
{
	char *data = NULL;
	data = new char[bufLen];

	if (recv(socketInfo, data, bufLen, NULL) != 0)
	{
		if (debug == true)
			ProcessError(WSAGetLastError());
		return 1;
	}
	else
	{
		memcpy(data, buffer, sizeof(data));
		return 0;
	}
}
  
The send function returns a WSAENOTCONN error (Socket is not connected). This is when sending for the first time from the host to the client. However, socketInfo does contain data and passed without error through the bind, listen, and accept process. My code probably sucks though. Any suggestions would be appreciated. Thanks for all your help.
There''s nothing wrong with that code, show me what the code around your calls to listen and accept look like...

codeka.com - Just click it.
Advertisement
send() returns the number of bytes sent, or -1 (error).
In your CNetwork::Send() function, you are indicating an error whenever you send anything. you should change your code from:
if (send(socketInfo, data, bufLen, NULL) != 0)
to something like
if (send(socketInfo, data, bufLen, NULL) == SOCKET_ERROR)
that way you will only process an error when you actually encounter an error
It is quite possible that you are sending fine, but because of that wrong if statement, you are simply getting the last error that occured which has nothing to do with the send() you just performed.
Oops, just looked at your receive code. You need to do the same thing there (change the if statement) because receive returns the number of bytes it has received. Also note that if recv returns 0 it means the other side has disconnected gracefully.
So you really need something like:
int dataReceived;if ((dataReceived = recv(socketInfo, data, bufLen, NULL)) == SOCKET_ERROR)	{	if (debug == true)			ProcessError(WSAGetLastError());		return 1;        }	else if ( dataReceived == 0 ){       // code for what happens when the other side disconnects}else {	memcpy(data, buffer, sizeof(data));        // an improvement here would be to minimize the copying        // by only copying the amount of data that was received        // (which may be less than bufLen)        // memcpy( data, buffer, dataReceived * sizeof(char) );		                 return 0;	}There hope that helps and is understandable.    
Thanks.. I had figured out the error on my own.. duh! Anyway, I have a new problem though.. the packets aren''t being sent right. Here is the new code:


  int CNetwork::Send(void *buffer, int bufLen){	char *data = NULL;	data = new char[bufLen];		memcpy(data, buffer, bufLen);		if (send(socketInfo, (char *)buffer, bufLen, NULL) == SOCKET_ERROR)	{		if (debug == true)			ProcessError(WSAGetLastError());		return 1;	}	else		return 0;	}int CNetwork::Receive(void *buffer, int bufLen){	char *data = NULL;	data = new char[bufLen];		if (recv(socketInfo, (char *)buffer, bufLen, NULL) == SOCKET_ERROR)	{		if (debug == true)			ProcessError(WSAGetLastError());		return 1;	}	else	{		memcpy(data, buffer, bufLen);			return 0;	}	}  


Then when I go to send and recieve information, I use the following code:


  struct packet_data{	string strData;};// code for client side// host send/recv is similarpacket_data newData;		packet_data recData;		net1.Receive(&recData, sizeof(packet_data));		cout << "Host said: " << recData.strData.c_str() << endl;		cout << "Enter text to send: ";		getline(cin, sendStr);		while (sendStr != "quit")		{			newData.strData = sendStr;						net1.Send(&newData, sizeof(packet_data));			net1.Receive(&newData, sizeof(packet_data));			cout << endl;			cout << "Host said: " << recData.strData.c_str() << endl;			cout << "Enter text to send: ";			getline(cin, sendStr);		}  


The packets displays garbage when I display out. Thanks a lot for any help you can give.

sizeof(packet_data) won''t be anything meaningful (I don''t know what it would be, my guess is around 4 or so).

To send an arbitrary amount of data, there''s two ways to go about it. One is to prefix the data with the size of the data, so if you''re going to send a 15 character string, send an integer 15 then the string. On the recieving end, read the integer, allocate a buffer and read however many characters it said.

The other method is to read one character at a time until you get to a special "end of message" marker, in the case of a simple string, then "end of message" marker would be the terminating NUL of the string.

Personally, I like the first method, it''s a little more general than the second.

codeka.com - Just click it.
Advertisement
Here is my updated code.. same error.. any more suggestions?

I hate debugging


  int CNetwork::Send(void *buffer, int bufLen){	char *data = NULL;	data = new char[bufLen];	char sendSize[10];	printf(sendSize, "%i", bufLen);	if (send(socketInfo, (char *)sendSize, sizeof(sendSize), NULL) == 0)		return 1; // disconnect		memcpy(data, buffer, bufLen);		if (send(socketInfo, (char *)data, bufLen, NULL) == SOCKET_ERROR)	{		if (debug == true)			ProcessError(WSAGetLastError());		return 1;	}	else		return 0;	}int CNetwork::Receive(void *buffer, int bufLen){	int msgSize = 0;	char recSize[10];		if (recv(socketInfo, recSize, sizeof(recSize), 0) == 0)		return 1; // disconnect		msgSize = atoi(recSize);		char *data = NULL;	data = new char[msgSize];		if (recv(socketInfo, (char *)data, msgSize, NULL) == SOCKET_ERROR)	{		if (debug == true)			ProcessError(WSAGetLastError());		return 1;	}	else	{		memcpy(buffer, data, msgSize);			return 0;	}	}  
use strlen if you want to get the length of the string

by saying sizeof(mystring), mystring is a pointer to the first element of the char array. you are getting the size of the pointer, which is 4 bytes on win32 machines. you are NOT getting the length of the string.
To be honest, you should step through your code with a debugger, it would have found a lot of the bugs.

The printf should really be a sprintf. Your compiler should have been warning about this and if you''re ignoring the warning then *cough* you shouldn''t. You''re getting rubbish because the array you''re filling in with the packet length isn''t being initialised by the printf (you need sprintf).
Note: A sensible limit for a packet of data is 65535 bytes. This can be expressed as two 8 bit values at the start of your packet data. It''s a bit of a waste to use 10 bytes encoded as a string to express this.

Also don''t use the suggestion of using strlen on your first string once your bug is fixed. Your code relies on the fact you''re using a series of ten bytes as the packet header. This part of the code is correct as sizeof(MyString) (I assume MyString is a replacement for ''sendSize'') will actually return the size of the array and not the size of the pointer. The size of the array is of course 10 chars so sizeof(sendSize) will be 10.

See how you go from there with that to begin with.


Martin Piper
Argonaut Games plc.
Martin Piper
When receiving data, you should memcpy only the amounty of data you received. When you send data, you might receive data in different sizes. Only the order and the total amount of data is the same. Also, on both send and receive you should delete the buffers you create because you will have BIG memory leaks. The user to be responsable for freeing data is a bad habit, so you should do it in your function.

Pet.

This topic is closed to new replies.

Advertisement