Socket Programming

Hi ,
I'm facing the following problem in socket programming.

My structure is

struct {
int i;
char *str;
}samp;

I'm creating the pointer to this structure and assigning the value to the structure members and send via the socket to the another process.

The receiver process when trying to print the data of this struct members , it is printing only the int data and the str data is missing.

I not able to find out where the problem actually lies.

sample code:

samp s1;
s1 = malloc(sizeof(samp);
s1-> i = 100;
s1->str = "Data";

send(sockfd, s1, sizeof(samp), 0);
// I don't know whether the above statement of data send is correct.

In the receiver end.

samp s2;
s2 = malloc(sizeof(samp));

recv(recvfd, s2, sizeof(samp), 0);

Also please add some note about how to pass the "pointer to a structure" date across the process using sockets.

Thanks in Advance,
Arun Viswanath

Pointers don't work that way. "str" is just an integer that points to memory local to a process, it won't be meaningful to whoever recieves it.

s1 has to be a pointer, since that is what malloc returns. But unless you need it to be persistent, you may not need to allocate it.

You can't declare a struct variable like "samp s1", you have to say "struct samp s1".

Try it like this:

struct {
  int i;
  char str[16];
}samp;

...

struct samp s1;

s1.i=1234;
strcpy(s1.str,"Data");

...

You could do a typedef and declare it as just 'samp s1'.

And about transferring the struct across sockets, there shouldn't be any problems there. Isn't it just a bunch of data? I thought you could transfer it just like you could transfer a string buffer.

Correct, the struct is just a bunch of data. Unfortunately the "char *str" element is just the memory address returned by malloc. It is not the data in that memory address.

So in the original code, what is being sent across the socket will be "meaningful" in that the receiver will understand it as a local memory address. Unfortunately, the data at that address in the receiver will not be the same as the data in that address in the originator.

It's worse than that, the string is a pointer to a memory constant.

Hi All,
Thanks for all your Info.
Event I tried changing my code , even now also i'm not getting my string printed.My code follows

my structure:
typedef struct
{
int i;
char *str; // things working fine when it is an array say char str[10]; But I want the pointer to void here.}samp;

server.c
    serv.sin_family = AF_INET;
    serv.sin_addr.s_addr = INADDR_ANY;
    serv.sin_port = htons(PORTNUM);

    mysocket = socket(AF_INET, SOCK_STREAM, 0);

    /* bind serv information to mysocket */
    if(bind(mysocket, (struct sockaddr *)&serv, sizeof(struct sockaddr)) < 0 )
     {
        printf("Cannot bind to port ");
     }

    /* start listening, allowing a queue of up to 1 pending connection */
    listen(mysocket, 1);
    while(1)
    {
        int consocket = accept(mysocket, (struct sockaddr *)&dest, &socksize);
        printf("Incoming connection from %s - sending welcome\n", inet_ntoa(dest.sin_addr));
        len = recv(consocket, (char *)s1, sizeof(samp), 0);
        printf("\n Rec data len : %d" , len);
        printf("\n Received Data : %d  %s\n", s1->i, s1->str);
        close(consocket);
    }
    close(mysocket);

client.c
    samp *s2;
    s2 = malloc(sizeof(samp));
    s2->i = 100;
    s2->str = malloc(10);
    strncpy(s2->str, "String", 10);
    mysocket = socket(AF_INET, SOCK_STREAM, 0);

    dest.sin_family = AF_INET;
    dest.sin_addr.s_addr = inet_addr("127.0.0.1");
    dest.sin_port = htons(PORTNUM);    
    if(connect(mysocket, (struct sockaddr *)&dest, sizeof(struct sockaddr)) < 0)
    {
       printf(" Connect Failed . No server Running \n");
    }

    send(mysocket, (char *)s2, sizeof(samp), 0);
    printf("Data send is : %d   %s \n", s2->i , s2->str);
         close(mysocket);

My server is listening for the data from client and prints the received data.
Please confirm the way I send and receive the data is correct

Using code tags for code makes it far more readable, as it presents it in a fixed-size font, allows indenting, and other such things. Use it like {code} int variable; {/code} except with instead of { }. I'll do this before I make a real reply so I can see your code better.

typedef struct
{
int i;
char *str; // things working fine when it is an array say char str[10]; But I want the pointer to void here.}samp;
    serv.sin_family = AF_INET;
    serv.sin_addr.s_addr = INADDR_ANY;
    serv.sin_port = htons(PORTNUM);

    mysocket = socket(AF_INET, SOCK_STREAM, 0);

    /* bind serv information to mysocket */
    if(bind(mysocket, (struct sockaddr *)&serv, sizeof(struct sockaddr)) < 0 )
     {
        printf("Cannot bind to port ");
     }

    /* start listening, allowing a queue of up to 1 pending connection */
    listen(mysocket, 1);
    while(1)
    {
        int consocket = accept(mysocket, (struct sockaddr *)&dest, &socksize);
        printf("Incoming connection from %s - sending welcome\n", inet_ntoa(dest.sin_addr));
        len = recv(consocket, (char *)s1, sizeof(samp), 0);
        printf("\n Rec data len : %d" , len);
        printf("\n Received Data : %d  %s\n", s1->i, s1->str);
        close(consocket);
    }
    close(mysocket);
    samp *s2;
    s2 = malloc(sizeof(samp));
    s2->i = 100;
    s2->str = malloc(10);
    strncpy(s2->str, "String", 10);
    mysocket = socket(AF_INET, SOCK_STREAM, 0);

    dest.sin_family = AF_INET;
    dest.sin_addr.s_addr = inet_addr("127.0.0.1");
    dest.sin_port = htons(PORTNUM);    
    if(connect(mysocket, (struct sockaddr *)&dest, sizeof(struct sockaddr)) < 0)
    {
       printf(" Connect Failed . No server Running \n");
    }

    send(mysocket, (char *)s2, sizeof(samp), 0);
    printf("Data send is : %d   %s \n", s2->i , s2->str);
         close(mysocket);

I'm sorry you need that feature, but pointers just don't work that way. That pointer is getting sent raw -- just a raw memory address, pointing to memory in your own process that the reciever simply doesn't have. The data you want remains squarely in your own process, untransmitted.

You'll have to either translate the structure instead of sending it raw, or use an array. Perhaps you could use a different method to denote NULL data? A negative size, maybye?

Translating it would look like this(pseudocode)

// Transmitter
transmit(&integer, sizeof(integer));
transmit(&length, sizeof(integer));
transmit(string,length);

// Reciever
char buf[512];
recieve(&integer,sizeof(integer));
recieve(&length,sizeof(integer));
recieve(buf, length);