2015-12-12 123 views
0

我正在嘗試編寫通過UDP進行通信的tic-tack-toe遊戲。 現在我有一些代碼:從緩存中獲取緩衝

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; 
    } 
} 

,現在我需要從recv_txt得到緩衝,把它裏面的結構是這樣的:

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

,並把它傳遞給新的線程。但我無法從recv_txt獲得緩衝區。我很新的C,現在我不能使用指針非常好。

感謝您的任何建議。

編輯

我試圖通過Frankie_c提供的解決方案,但我有問題,現在printf。 當我嘗試在main

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

我沒有得到任何打印到控制檯或遇到錯誤信息。

EDIT2 - 全碼

#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; 
} 

和接收數據包後,我得到:

received: Hello 192.168.56.1 
Segmentation fault (code dumped) 

Process returned 139 (0x8B) 
+0

您是否考慮過使用更高級別的語言編寫此程序?你想要做的事情是可能的,但是你在極深的一端跳進了鯊魚坦克。 – zwol

+0

但是如何從'recv_txt'獲得緩衝區,它接收到的緩衝區只是該函數的本地區域,您不會將其返回或複製到作爲參數傳遞的緩衝區。 –

+0

@zwol 我知道,但我沒有選擇。這是從學校項目和客戶端這個遊戲是用Java編寫的,但服務器必須在C. – Sk1X1

回答

1

對於原來的問題試試這個:

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!!! 
    } 
} 

編輯:你的問題是你不返回分配結構成功時,並且在失敗時不返回NULL。請參閱:

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; 
} 
+0

感謝您的答覆。我試過你的解決方案,現在我遇到了'printf'的問題。我用精確的代碼編輯了我的問題。你能告訴我做錯了什麼嗎? – Sk1X1

+0

我誤解了你的評論。抱歉。無論如何,我更新了我的答案在接收例程printf中的錯誤。讓我看看更好看。 –

+0

感謝您的幫助,'recv_txt'中的'printf'現在運行良好,但我不知道如何修復'main'中的'printf'。 另外我編輯我的問題,以提供我的'printf'錯誤的更具體位置。 – Sk1X1