0

I'm trying to write tic-tack-toe game communicates through UDP. For now I have code:

int recv_txt(int sock, struct sockaddr_in *incoming_addr)
{
    char bud[MAX_LENGTH];
    unsigned int incoming_add_len;
    incoming_add_len = sizeof(*incoming_addr);
    if(recvfrom(sock, &buf, MAX_LENGTH, 0 (struct sockaddr*)incoming_addr, &incoming_addr_len) < 0)
    {
         return 0;
    }
    printf("received %s", buf);
    return 1;
}

int main(int argv, char **argc)
{
    /** some code to create socket etc */
    struct sockaddr_in incoming_addr;
    for(;;)
    {
        recv_txt(sock, &incoming_addr);

       //here I would like to create new thread, which will process the buffer from recv_txt and send response;
    }
}

and now I need to get buffer from recv_txt, put it inside structure like this:

struct M_s
{
    struct sockaddr_in address;
    char[MAX_LENGTH] buffer;
}

and pass it to new thread. But I can't get the buffer from recv_txt. Im pretty new in C and for now i can't work with pointers very well.

Thanks for any advice.

EDIT

I tried solution provided by Frankie_c, but I have problem with printf now. When I try in main:

LP_ARGS_STRUCT args = recv_txt(sock)
printf("data from: %s", inet_ntoa(args->address.sin_adrr))

i don't get any print to console or get error message.

EDIT2 - full code

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <pthread.h>

#define SRV_PORT            23456
#define MAX_TXT_LENGTH      1000
#define MAX_ROOMS           1

int sock;

typedef struct args_s
{
    struct sockaddr_in address;
    char buffer[MAX_TXT_LENGTH];
} ARGS_STRUCT, *LP_ARGS_STRUCT;
//typedef struct args_s args;


LP_ARGS_STRUCT recv_txt(int sock)
{
    LP_ARGS_STRUCT args = malloc(sizeof(ARGS_STRUCT));

    //memory error
    if(!args)
    {
        return 1;
    }

    unsigned int incoming_addr_len = sizeof(args->address);

    //incoming_addr_len = sizeof(*incoming_addr);
    if (recvfrom(sock, &args->buffer, MAX_TXT_LENGTH, 0,
                    (struct sockaddr*)&args->address, &incoming_addr_len) < 0)
    {
        free(args);
        return NULL;
    }
    printf("received: %s %s\n", args->buffer, inet_ntoa(args->address.sin_addr));
    return 1;
}

int main(int argv, char **argc)
{
    int i = 0;

    int optval;
    struct sockaddr_in addr, incoming_addr;
    char buffer[MAX_TXT_LENGTH];

    /* create socket */
    sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (sock < 0)
    {
        err("socket()");
    }

    /* set reusable flag */
    optval = 1;
    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));

    /* prepare inet address */
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(SRV_PORT);
    addr.sin_addr.s_addr = htonl(INADDR_ANY); /* listen on all interfaces */
    if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0)
    {
        err("bind");
    }


    for(;;)
    {


        LP_ARGS_STRUCT args = recv_txt(sock);
        if(!args) continue;
        printf("%s\n", args->buffer);

    }

    return 0;
}

and after receiving a packet I get:

received: Hello 192.168.56.1
Segmentation fault (code dumped)

Process returned 139 (0x8B)
Sk1X1
  • 1,305
  • 5
  • 22
  • 50
  • Have you considered using a higher-level language to write this program? What you want to do is possible, but you're jumping into the shark tank at the very deep end. – zwol Dec 12 '15 at 18:09
  • But how could you get the buffer from `recv_txt`, the buffer it receives to is just local to the function, you don't return it or copy to a buffer passed as an argument. – Some programmer dude Dec 12 '15 at 18:09
  • @zwol I know, but I don't have choice. It's from school project and client side of this game is written in Java, but server has to be in C. – Sk1X1 Dec 12 '15 at 18:10
  • @JoachimPileborg I would like to get it with same way like `incoming_addr`. Add new parameter to `recv_txt` and through this parameter return this buffer. – Sk1X1 Dec 12 '15 at 18:12
  • Of course, if is here any better solution how to resolve this, i'm open ear – Sk1X1 Dec 12 '15 at 18:13
  • If you are going to signal the data to another thread, it's easiest if you dynamically alloacte your 'M_s' buffer struct with malloc. recvFrom() straight into the struct and set the length, queue/createThread off the struct pointer to your thread. free the struct in the message-handling thread when you are done with it. – Martin James Dec 12 '15 at 18:27
  • @JoachimPileborg Heh, easiest :D can you please provide some example code? From yours text I have no clue how to start – Sk1X1 Dec 12 '15 at 18:39

1 Answers1

1

For the original question try this:

typedef struct M_s
{
    struct sockaddr_in address;
    char[MAX_LENGTH] buffer;
} M_STRUCT, *LP_M_STRUCT;   //Create a typedef for struct

//Modify your function to return a structure pointer and having just socket as par...
LP_M_STRUCT recv_txt(int sock)
{
    LP_M_STRUCT pMs = malloc(sizeof(M_STRUCT));
    if (!pMs)
    {
        //Handle memory error here!
        return NULL;
    }

    unsigned int incoming_add_len = sizeof(pMs->incoming_addr);

    if (recvfrom(sock, &pMs->buffer, MAX_LENGTH, 0, (struct sockaddr *)&pMs->incoming_addr, &incoming_addr_len) < 0)
    {
        free(pMs);      //Release memory
        return NULL;    //Return nothing...
    }

    //If we are here we were successfull.
    //The structure pMs holds all data we need... so give it to caller...
    printf("From %s received %s", inet_ntoa(pMs->address.sin_addr), pMs->buffer);
    return pMs;
}

int main(int argv, char **argc)
{
    /** some code to create socket etc */

    for (;;)
    {
        LP_M_STRUCT pMs = recv_txt(sock);
        if (!pMs)   //Check if we get a sign of life on UDP...
            continue;   //No continue to wait for ...

         //We print values again to check that it is ok...
         printf("From %s received %s", inet_ntoa(pMs->address.sin_addr), pMs->buffer);

        //here create new thread to process the buffer from recv_txt and send response;
        //The new thread code have to release structure memory when done!!!
    }
}

EDIT: Your problem is that you don't return the allocated structure when successfull and don't return NULL when fail. See:

LP_ARGS_STRUCT recv_txt(int sock)
{
    LP_ARGS_STRUCT args = malloc(sizeof(ARGS_STRUCT));

    //memory error
    if(!args)
    {
        //return 1;    !!!WRONG!!!
        return NULL;
    }

    unsigned int incoming_addr_len = sizeof(args->address);

    //incoming_addr_len = sizeof(*incoming_addr);
    if (recvfrom(sock, &args->buffer, MAX_TXT_LENGTH, 0,
                    (struct sockaddr*)&args->address, &incoming_addr_len) < 0)
    {
        free(args);
        return NULL;
    }
    printf("received: %s %s\n", args->buffer, inet_ntoa(args->address.sin_addr));
    //return 1;    WRONG! You have to return the allocated struct
    return args;
}
Frankie_C
  • 4,764
  • 1
  • 13
  • 30
  • Thanks for reply. I tried your solution and now I have problem with `printf`. I edited my question with exact code. Can you please tell what I'm doing wrong? – Sk1X1 Dec 12 '15 at 19:38
  • I misunderstood your comment. Sorry. Anyway I updated my answer for an error in the printf of receive routine. Let me have a better look. – Frankie_C Dec 12 '15 at 19:51
  • Thanks for help, `printf` in `recv_txt` works well now, but I don't know how to fix my `printf` in `main`. Also I edited my question to provide more specific location of my `printf` error. – Sk1X1 Dec 12 '15 at 20:06
  • As far as I can see my code should be correct. Try to print both buffer and partner address in the receive routine (see the updated answer). If it works there your problem should be elsewhere, maybe in the routing of the structure to the freshly created thread. – Frankie_C Dec 12 '15 at 20:13
  • The `prinft` you added in last edit is the problem. If I try to `printf` `address` or `buffer` from `pMs` I got `Segmentation fault`. For now I don't use any threads, just code from you. – Sk1X1 Dec 12 '15 at 20:28
  • You mean that in the `main` printing the result, when `pMs!=NULL` give segfault? That makes no sense. Could you show all your code, there should be some stupid error in between... – Frankie_C Dec 12 '15 at 20:55
  • See the solution edit. And don't forget to accept and vote. – Frankie_C Dec 13 '15 at 14:10
  • Oh, my bad :( I was working on my code for more than six hours and just didn't saw this :/ thx a lot ! – Sk1X1 Dec 13 '15 at 15:37