C Board  

Go Back   C Board > General Programming Boards > C++ Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 06-20-2009, 02:14 PM   #1
Registered User
 
Join Date: Nov 2002
Posts: 249
trying to send a struct over a socket

i am not seeing a = 50; b = 100; c = 200; in the recv buffer, i am only seeing a = 50;
what is the problem?
Code:
// tcp.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <vector>
#include <windows.h>
#include <iostream>
#include <list>
#include <stdio.h>
#include <d3dx9.h>
#pragma comment(lib,"ws2_32.lib")

using namespace std;

class Data
{
public:
	int a;
    int b;
    int c;
protected:
private:

};

class TcpClient
{
public:
	void InitWinsock()
	{
		Result = WSAStartup(MAKEWORD(2, 2), &WSAdata);
		if(Result == -1)
		{
			printf("%s\n","Setting Up Winsock Failed!");
		}
		else
		{
			printf("%s\n","Setting Up Winsock Success!");
		}
	}

	void SetAddressInfo()
	{
		memset(&sins, 0, sizeof(sins));
		ConnectSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
		sins.sin_family = AF_INET;
        sins.sin_port = htons(50);
		sins.sin_addr.s_addr = inet_addr("192.168.1.100");
	}

	void ConnectInfo()
	{
	   if(connect(ConnectSock, (sockaddr *)&sins, sizeof(SOCKADDR_IN))== SOCKET_ERROR)
	   { 
		   printf("%s\n","Failed To Connect!");
	   }
       else
	   {
		   printf("%s\n","Connected To Server!");
	   }
	}

	void SendToSocket(char*Data)
	{
		while(1)
		{
		  // printf("%s\n","Enter Something To Send!");
		  // cin >> Something;
		   Result = send(ConnectSock,Data,sizeof(Data),0);
		   if(Result == -1)
		   {
			  printf("%s\n","Failed To Send Data!");
			  break;
		   }
		   else
		   {
			  printf("%s\n","Data Sent!");
		   }
		}
		
		
	}

protected:

private:
	WSADATA WSAdata;
	SOCKET ConnectSock;
	sockaddr_in sins;
	int Result;
	char Something[64];
	
	
};

class TcpServer
{
public:
	void InitWinsock()
	{
		Result = WSAStartup(MAKEWORD(2, 2), &WSAdata);
		if(Result == -1)
		{
			printf("%s\n","Setting Up Winsock Failed!");
		}
		else
		{
			printf("%s\n","Setting Up Winsock Success!");
		}
	}

	void SetAddressInfo()
	{
		memset(&sins, 0, sizeof(sins));
		ListenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
		sins.sin_family = AF_INET;
        sins.sin_port = htons(50);
		sins.sin_addr.s_addr = inet_addr("192.168.1.100");
	}

	void BindnListen()
	{
		if( bind( ListenSock, (struct sockaddr*)&sins, sizeof( struct sockaddr)) == SOCKET_ERROR )
        {
			printf("%s\n","Failed To Bind To Address!");
		}
	    else
	    {
			printf("%s\n","Binded To Address Success!");
	    }

		if(listen(ListenSock, 1)==SOCKET_ERROR)
	    {
			printf("%s\n","Failed To Listen On Address!");
		}
	    else
	    {
			printf("%s\n","Listening On Address!");
		}
	}
	
	void WaitForConnections()
	{
		while(1)
		{
			printf("%s\n","Waiting For Connections!");

			AcceptSock = accept(ListenSock , (struct sockaddr*)&sins,0);
		    if(AcceptSock == SOCKET_ERROR)
		    {
				printf("%s\n","No Connection Made Yet!");
		    }
		    else
		    {
				printf("%s\n","Connection Made!");
				break;
		    }
	   }
	}

	void RecieveFromSocket()
	{
		while(1)
		{
			if(AcceptSock != INVALID_SOCKET)
			{
				recv(AcceptSock,(char*)&DataObject,sizeof(DataObject),0);
				//RecvBuffer[strlen(RecvBuffer)-1] = '\0';
		        printf("%d\n",DataObject.a);
				printf("%d\n",DataObject.b);
				printf("%d\n",DataObject.c);
		    }
			else
			{
				printf("%s\n","No Connection Yet!");
			}
		}
	}

	

protected:

private:
	WSADATA WSAdata;
	SOCKET ListenSock;
	SOCKET AcceptSock;
	sockaddr_in sins;
	int Result;
	char RecvBuffer[512];
	Data DataObject;

};



#define SERVER
//#define CLIENT

int _tmain(int argc, _TCHAR* argv[])
{
	Data DataObject;
	DataObject.a = 50;
	DataObject.b = 100;
	DataObject.c = 200;

#ifndef CLIENT

	TcpClient TcpClientObject;
	TcpClientObject.InitWinsock();
	TcpClientObject.SetAddressInfo();
	TcpClientObject.ConnectInfo();
	TcpClientObject.SendToSocket((char*)&DataObject);

#endif
	
	
#ifndef SERVER
	
	TcpServer TcpServerObject;
	TcpServerObject.InitWinsock();
	TcpServerObject.SetAddressInfo();
	TcpServerObject.BindnListen();
	TcpServerObject.WaitForConnections();
	TcpServerObject.RecieveFromSocket();

#endif
	
	

	

	
	

	return 0;
}
__________________

Last edited by Anddos; 06-20-2009 at 02:28 PM.
Anddos is offline   Reply With Quote
Old 06-20-2009, 02:51 PM   #2
and the hat of vanishing
 
Salem's Avatar
 
Join Date: Aug 2001
Location: The edge of the known universe
Posts: 21,214
Both send() and recv() can fragment the data.
You need to check for this, and possibly reassemble the message.
__________________
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
Up to 8Mb PlusNet broadband from only £5.99 a month!
Salem is offline   Reply With Quote
Old 06-20-2009, 09:42 PM   #3
Registered User
 
Join Date: Jan 2008
Posts: 575
Quote:
Both send() and recv() can fragment the data.
He is using a TCP socket. (Message fragmentation and reassembly should be transparent to the application.)

Code:
Result = send(ConnectSock,Data,sizeof(Data),0);
This is the problem. (The variable `Data' is a pointer.)

Code:
void SendToSocket(char*Data, int size)
// ...
Result = send(ConnectSock,Data,size,0);
// ...
Code:
TcpClientObject.SendToSocket((char*)&DataObject, sizeof(DataObject));
You should be able to see the implications.

Soma
phantomotap is offline   Reply With Quote
Old 06-20-2009, 10:14 PM   #4
int x = *((int *) NULL);
 
Cactus_Hugger's Avatar
 
Join Date: Jul 2003
Location: Banks of the River Styx
Posts: 890
Your analysis of the issue with the pointer is correct, however this:
Quote:
He is using a TCP socket. (Message fragmentation and reassembly should be transparent to the application.)
...is not. An application will have to deal with it. If a call to send() gets split into two packets, the other end's recv() may only read 1 of those packets (if the other has not yet arrived). A second (or possibly more) call to recv() is needed.
Same with send() - depending on conditions, the call may only send part of the packet.

In both cases, the answer is simple: check the return value. send() may not send everything you ask of it, recv() may not completely fill the recv() buffer.
__________________
long time; /* know C? */
Unprecedented performance: Nothing ever ran this slow before.
Any sufficiently advanced bug is indistinguishable from a feature.
Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
The best way to accelerate an IBM is at 9.8 m/s/s.
recursion (re - cur' - zhun) n. 1. (see recursion)
Cactus_Hugger is offline   Reply With Quote
Old 06-20-2009, 10:20 PM   #5
Registered User
 
Join Date: Jan 2008
Posts: 575
O_o

The packet is definitely less than 576 bytes, so I don't know how a TCP packet could be split, but sure, maybe I'm wrong.

Sorry for any confusion on the issue if I am...

Soma
phantomotap is offline   Reply With Quote
Old 06-20-2009, 10:49 PM   #6
int x = *((int *) NULL);
 
Cactus_Hugger's Avatar
 
Join Date: Jul 2003
Location: Banks of the River Styx
Posts: 890
I assumed that since we're sending three integers named 'a', 'b', and 'c', that this is a simple test example.

The point is that the interface provided by send() and recv() specifies that both function may not send or recv all of the data. & you should check the error codes.
__________________
long time; /* know C? */
Unprecedented performance: Nothing ever ran this slow before.
Any sufficiently advanced bug is indistinguishable from a feature.
Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
The best way to accelerate an IBM is at 9.8 m/s/s.
recursion (re - cur' - zhun) n. 1. (see recursion)
Cactus_Hugger is offline   Reply With Quote
Old 06-20-2009, 11:00 PM   #7
Registered User
 
Join Date: Jan 2008
Posts: 575
O_o

No one is arguing with you... (at least I'm not)

Soma
phantomotap is offline   Reply With Quote
Old 06-20-2009, 11:00 PM   #8
Registered User
 
Join Date: Dec 2007
Location: France
Posts: 395
You should use WSACleanup() too.

And why use both
#include <iostream>
#include <stdio.h>
in a c++ program.
__________________
Using Code::Blocks,MingW with Windows.
Ducky is offline   Reply With Quote
Old 06-20-2009, 11:20 PM   #9
Senior software engineer
 
brewbuck's Avatar
 
Join Date: Mar 2007
Location: Portland, OR
Posts: 5,357
Quote:
Originally Posted by Cactus_Hugger View Post
Your analysis of the issue with the pointer is correct, however this:
...is not. An application will have to deal with it. If a call to send() gets split into two packets, the other end's recv() may only read 1 of those packets (if the other has not yet arrived). A second (or possibly more) call to recv() is needed.
That's not fragmentation. That's simply incomplete receive. It could happen for many reasons, only one of which is that the packet got fragmented. It could simply be that some internal buffer has filled, for instance.

Dealing with actual fragmentation is difficult because packets can arrive in a different order than which they were sent. But with a TCP socket the data is guaranteed to be in order, it just may not all arrive in a single call to recv(). (The socket layer is what puts the fragments back together and makes sure the data is in the proper order)

It's not a hard problem. Keep calling recv() until you've received all the data you expect.
__________________
"Congratulations on your purchase. To begin using your quantum computer, set the power switch to both off and on simultaneously." -- raftpeople@slashdot
brewbuck is offline   Reply With Quote
Old 06-27-2009, 10:27 AM   #10
Registered User
 
Join Date: Dec 2007
Location: France
Posts: 395
I cant make your program to connect and i think i know why.

When you call your client to connect you havent yet set up your server to accept
connections.

But if i turn around the logic and call the server first, it gets stuck in the
void WaitForConnections() function because its an infinite loop:
its waiting for a conection but to connect he should get out of the loop to call the
client to connect.

Though you said you managed to connect with it, i wonder how?
__________________
Using Code::Blocks,MingW with Windows.
Ducky is offline   Reply With Quote
Old 06-27-2009, 10:50 AM   #11
Registered User
 
Join Date: Jan 2008
Posts: 575
"192.168.1.100"

Is that your IP address?

Soma
phantomotap is offline   Reply With Quote
Old 06-27-2009, 02:56 PM   #12
Registered User
 
Join Date: Dec 2007
Location: France
Posts: 395
No, no im not that lame!

I changed it to 127.0.0.1.

Thanks though!
__________________
Using Code::Blocks,MingW with Windows.
Ducky is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Casting a struct for sending to socket chrisjmoss Networking/Device Communication 6 04-08-2008 09:11 AM
Looking for a way to store listbox data Welder C Programming 20 11-01-2007 11:48 PM
Socket or send() problem? Achy C Programming 5 06-09-2006 01:09 PM
Request for comments Prelude A Brief History of Cprogramming.com 15 01-02-2004 10:33 AM
Bi-Directional Linked Lists Thantos C Programming 6 12-11-2003 10:24 AM


All times are GMT -6. The time now is 02:59 PM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0 RC2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22