Thread: trying to send a struct over a socket

  1. #1
    Registered User
    Join Date
    Nov 2002
    Posts
    319

    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.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    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.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    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

  4. #4
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    Your analysis of the issue with the pointer is correct, however this:
    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)

  5. #5
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    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

  6. #6
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    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)

  7. #7
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

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

    Soma

  8. #8
    Registered User
    Join Date
    Dec 2007
    Posts
    930
    You should use WSACleanup() too.

    And why use both
    #include <iostream>
    #include <stdio.h>
    in a c++ program.
    Using Windows 10 with Code Blocks and MingW.

  9. #9
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    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.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  10. #10
    Registered User
    Join Date
    Dec 2007
    Posts
    930
    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 Windows 10 with Code Blocks and MingW.

  11. #11
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    "192.168.1.100"

    Is that your IP address?

    Soma

  12. #12
    Registered User
    Join Date
    Dec 2007
    Posts
    930
    No, no im not that lame!

    I changed it to 127.0.0.1.

    Thanks though!
    Using Windows 10 with Code Blocks and MingW.

Popular pages Recent additions subscribe to a feed

Similar Threads

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