'发送失败';使用sendto-function时出错,在C中使用UDP套接字

时间:2012-03-25 15:16:12

标签: c sockets

我有一个程序,它是FEC编码数据,发送数据;在另一个套接字接收数据,并解码数据。

在下面附带的代码中执行sendto-function时出错。有关sendto-function的更多信息,请访问:Link 错误的返回码是' -1'。

此错误的原因是什么?我应该在代码中更改哪些内容才能解决它?

来自'接收器'

的打印件
*** Sender -- socket created 
***we have a client, and will sent message to server_addr ...server.. will receive messages.. sss
*** Created server socket good. Server socket is 4 
***We have a server socket; and now we will try to bind it with the IP_ADDR-local host -- that we sent.. 
 port nr 4783 & ip 127.0.0.1***Bind succeed.. 
Thread 1 

eperftool.h的一些行

 #define  PORT_NUM   4783    // Arbitrary port number for the server
  #define  IP_ADDR      "127.0.0.1" // IP address of server1 (*** HARDWIRED ***)
  #define  SYMBOL_SIZE 1024 //todo..on a different position also
  #define MAX_K     1000
   #define MAX_N        1500

sender.c的代码:

 /* $Id: sender.c 3 2011-03-03 10:48:54Z detchart $ */
/*
 * OpenFEC.org AL-FEC Library.
 * (c) Copyright 2009-2011 INRIA - All rights reserved
 * Contact: vincent.roca@inria.fr
 *
 * This software is governed by the CeCILL-C license under French law and
 * abiding by the rules of distribution of free software.  You can  use,
 * modify and/ or redistribute the software under the terms of the CeCILL-C
 * license as circulated by CEA, CNRS and INRIA at the following URL
 * "http://www.cecill.info".
 *
 * As a counterpart to the access to the source code and  rights to copy,
 * modify and redistribute granted by the license, users are provided only
 * with a limited warranty  and the software's author,  the holder of the
 * economic rights,  and the successive licensors  have only  limited
 * liability.
 *
 * In this respect, the user's attention is drawn to the risks associated
 * with loading,  using,  modifying and/or developing or reproducing the
 * software by the user in light of its specific status of free software,
 * that may mean  that it is complicated to manipulate,  and  that  also
 * therefore means  that it is reserved for developers  and  experienced
 * professionals having in-depth computer knowledge. Users are therefore
 * encouraged to load and test the software's suitability as regards their
 * requirements in conditions enabling the security of their systems and/or
 * data to be ensured and,  more generally, to use and operate it in the
 * same conditions as regards security.
 *
 * The fact that you are presently reading this means that you have had
 * knowledge of the CeCILL-C license and that you accept its terms.
 */


/* AL-FEC extended performance evaluation tool */

#include "eperftool.h"



/*
 * local variables
 */
static void     **encoding_symbols_tab; /* temporary symbol array needed by the FEC encoder */

of_status_t
init_sender (void)
{
    of_session_t    *ses;       /* pointer to a codec instance */
    block_cb_t  *blk;       /* temporary pointer within the blk_cb_tab[] */
    UINT32      sbn;        /* block sequence number */
    UINT32      k;      /* k parameter for a given block. Warning, the last block might be shorter */
    UINT32      n;      /* n parameter for a given block. Warning, the last block might be shorter */
    UINT32      esi;        /* Encoding Symbol ID */
    UINT32      src_idx;    /* index for a source symbol in the orig_symb[] table */
    UINT32      rep_idx;    /* index for a repair symbol in the orig_symb[] table */
    symbol_cb_t *src_symb_cb;   /* pointer to a source symbol in the orig_symb[] table */
    symbol_cb_t *rep_symb_cb;   /* pointer to a repair symbol in the orig_symb[] table */
    UINT32      tmp_max_k;  /* temporary value for max_k */
    UINT32      max_n_4_any_blk;/* maximum n value for any block */


#ifdef WIN32
    QueryPerformanceCounter(&tv0);
    OF_PRINT(("init_start=%lI64f\n", (double)tv0.QuadPart/(double)freq.QuadPart))
#else
    gettimeofday(&tv0, NULL);
    OF_PRINT(("init_start=%ld.%ld\n", tv0.tv_sec, tv0.tv_usec))
#endif
    /*
     * determine the blocking structure, which requires to create a temporary FEC session.
     */
    if (of_create_codec_instance(&ses, codec_id, OF_ENCODER, of_verbosity) != OF_STATUS_OK) {
        OF_PRINT_ERROR(("init_sender: ERROR: of_create_codec_instance() failed\n"))
        goto error;
    }
    if (codec_id == OF_CODEC_REED_SOLOMON_GF_2_M_STABLE) {
        if (of_set_control_parameter(ses, OF_RS_CTRL_SET_FIELD_SIZE, (void*)&rs_m_param, sizeof(rs_m_param)) != OF_STATUS_OK) {
            OF_PRINT_ERROR(("init_sender: ERROR: of_set_control_parameter() failed\n"))
            goto error;
        }
    }
    if (of_get_control_parameter(ses, OF_CTRL_GET_MAX_K, (void*)&max_k, sizeof(max_k)) != OF_STATUS_OK) {
        OF_PRINT_ERROR(("init_sender: ERROR: of_get_control_parameter() failed\n"))
        goto error;
    }
    if (of_get_control_parameter(ses, OF_CTRL_GET_MAX_N, (void*)&max_n, sizeof(max_n)) != OF_STATUS_OK) {
        OF_PRINT_ERROR(("init_sender: ERROR: of_get_control_parameter() failed\n"))
        goto error;
    }
    if (of_release_codec_instance(ses) != OF_STATUS_OK) {
        OF_PRINT_ERROR(("init_sender: ERROR: of_release_codec_instance() failed\n"))
        goto error;
    }

    /*
     * determine the practical maximum k and n parameters, taking into
     * account the code/codec limitations and the desired code_rate.
     * The idea is to have max_k maximum, given max_n and code_rate, for
     * optimal erasure recovery performances.
     */
    tmp_max_k = (UINT32)floor((double)max_n * code_rate);
    max_k = min(tmp_max_k, max_k);
    max_n = min((UINT32)((double)max_k / code_rate), max_n);
    /* we can now compute the required blocking structure */
    of_compute_blocking_struct(max_k, object_size, symbol_size, &bs);
    tot_nb_blocks = bs.nb_blocks;
    /*
     * adjust tot_nb_encoding_symbols and tot_nb_encoding_symbols variables, now we know
     * the exact blocking structure.
     */
    tot_nb_encoding_symbols = (bs.I * (int)floor((double)(bs.A_large) / code_rate)) +
                  ((bs.nb_blocks - bs.I) * (int)floor((double)(bs.A_small) / code_rate));

    ASSERT(tot_nb_encoding_symbols <= tot_nb_source_symbols + tot_nb_repair_symbols);
    tot_nb_repair_symbols = tot_nb_encoding_symbols - tot_nb_source_symbols;

    OF_PRINT_LVL(1, ("Blocking_struct:\n\ttot_nb_source_symbols=%d, tot_nb_repair_symbols=%d, tot_nb_encoding_symbols=%d, code_rate=%.3f\n\tI=%d, tot_nb_blocks=%d, A_large=%d, A_small=%d\n",
        tot_nb_source_symbols, tot_nb_repair_symbols, tot_nb_encoding_symbols, code_rate,
        bs.I, tot_nb_blocks, bs.A_large, bs.A_small))

    /*
     * allocate and inix@tialize the original source and repair symbol buffers.
     */
    if ((orig_symb = (char**)calloc(tot_nb_encoding_symbols, sizeof(char*))) == NULL) {
        OF_PRINT_ERROR(("init_sender: ERROR: out of memory\n"))
        goto no_mem;
    }
    /* source symbol buffers first... */
    for (src_idx = 0; src_idx < tot_nb_source_symbols; src_idx++) {
        char    *symb;
        UINT32  i;
        /*
         * buffer is 0'ed... Leave it like that, except for the first
         * four bytes where we copy the pkt seq number.
         */
        if ((symb = (char*)calloc(1, symbol_size)) == NULL) {
            OF_PRINT_ERROR(("init_sender: ERROR: out of memory\n"))
            goto no_mem;
        }
        orig_symb[src_idx] = symb;
        /* fill each source symbol with some random content, except the first
         * word which is equal to the symbol ID. This is useful to test the symbol
         * integrity after decoding */
        for (i = 0; i < symbol_size; i++) {
            symb[i] = (char)rand();

        }
        *(UINT32 *)symb = (UINT32)src_idx;
        //symb[src_idx%symbol_size]=1;
        //of_print_composition(symb, symbol_size);
    }
    /* ... and then repair symbol buffers */
    for (rep_idx = tot_nb_source_symbols; rep_idx < tot_nb_encoding_symbols; rep_idx++) {
            orig_symb[rep_idx] = (char*)calloc(1, symbol_size);
        if (orig_symb[rep_idx] == NULL)  {
            OF_PRINT_ERROR(("init_sender: ERROR: out of memory\n"))
            goto no_mem;
        }
        /* repair symbols will be initialized later... */
    }
    /*
     * now allocate the block and symbol control structures.
     */
    if (!(blk_cb_tab = (block_cb_t*)calloc(tot_nb_blocks, sizeof(block_cb_t)))) {
        OF_PRINT_ERROR(("init_sender: ERROR: out of memory\n"))
        goto no_mem;
    }
    if (!(symb_cb_tab = (symbol_cb_t*)calloc(tot_nb_encoding_symbols, sizeof(symbol_cb_t)))) {
        OF_PRINT_ERROR(("init_sender: ERROR: out of memory\n"))
        goto no_mem;
    }
    /* ...and initialize the various block/symbol control structures */
    src_idx     = 0;
    src_symb_cb = symb_cb_tab;
    rep_idx     = tot_nb_source_symbols;
    rep_symb_cb = &(symb_cb_tab[tot_nb_source_symbols]);
    max_n_4_any_blk = 0;
    for (sbn = 0, blk = blk_cb_tab; sbn < tot_nb_blocks; sbn++, blk++) {
        if (sbn < (UINT32)bs.I) {
            k = bs.A_large;
        } else {
            k = bs.A_small;
        }
        n = (UINT32)floor((double)k / code_rate);
        max_n_4_any_blk = (n < max_n_4_any_blk) ? max_n_4_any_blk : n;
        /* init block control block */
        blk->sbn            = sbn;
        blk->k              = k;
        blk->n              = n;
        blk->first_src_symbol_idx   = src_idx;
        blk->first_repair_symbol_idx    = rep_idx;
        blk->is_decoded         = false;
        blk->nb_symbols_received    = 0;
        OF_TRACE_LVL(1, ("init_sender: block: sbn=%d, k=%d, n=%d, first_src_symbol_idx=%d, 1st_rep_symbol_idx=%d\n",
            sbn, blk->k, blk->n,
            blk->first_src_symbol_idx, blk->first_repair_symbol_idx))
        /* init source symbols control block */
        for (esi = 0; esi < k; esi++, src_symb_cb++, src_idx++) {
            src_symb_cb->esi = esi;
            src_symb_cb->sbn = sbn;
        }
        /* and init repair symbols control block */
        for (esi = k; esi < n; esi++, rep_symb_cb++, rep_idx++) {
            rep_symb_cb->esi = esi;
            rep_symb_cb->sbn = sbn;
        }
    }
    /*
     * allocate the table containing the various symbols of a block. This table
     * is allocated once and reused by all blocks of the object, with pointers to
     * different symbols of course, for encoding purposes.
     */
    if (!(encoding_symbols_tab = (void**)calloc(max_n_4_any_blk, sizeof(void*)))) {
        OF_PRINT_ERROR(("init_sender: ERROR: out of memory\n"))
        goto no_mem;
    }
#ifdef WIN32
    QueryPerformanceCounter(&tv1);
    OF_PRINT(("init_end=%I64f  init_time=%I64f\n",
        (double)tv1.QuadPart / (double)freq.QuadPart,
        (double)(tv1.QuadPart-tv0.QuadPart) / (double)freq.QuadPart ))
#else
    gettimeofday(&tv1, NULL);
    timersub(&tv1, &tv0, &tv_delta);
    OF_PRINT(("init_end=%ld.%ld  init_time=%ld.%06ld\n",
        tv1.tv_sec, tv1.tv_usec, tv_delta.tv_sec, tv_delta.tv_usec))
#endif

    //INIT SENDER SOCKET
       // >>> Step #1 <<<
      // Create a socket
      //   - AF_INET is Address Family Internet and SOCK_DGRAM is datagram
      client_s = socket(AF_INET, SOCK_DGRAM, 0);
      if (client_s < 0)
      {
        printf("*** ERROR - socket() failed \n");
        exit(-1);
      }
        printf("*** Sender -- socket created \n");
      // >>> Step #2 <<<
      // Fill-in server1 socket's address information
      server_addr.sin_family = AF_INET;                 // Address family to use
      server_addr.sin_port = htons(PORT_NUM);           // Port num to use
      server_addr.sin_addr.s_addr = inet_addr(IP_ADDR); // IP address to use 

                printf("***we have a client, and will sent message to server_addr ...server.. will receive messages.. sss\n");
    return OF_STATUS_OK;
no_mem:
error:
    return OF_STATUS_ERROR;
}


of_status_t
encode (void)
{
    of_session_t    *ses;       /* pointer to a codec instance */
    block_cb_t  *blk;       /* temporary pointer within the blk_cb_tab[] */
    UINT32      sbn;        /* block sequence number */
    UINT32      k;      /* k parameter for a given block. Warning, the last block might be shorter */
    UINT32      n;      /* n parameter for a given block. Warning, the last block might be shorter */
    UINT32      esi;        /* Encoding Symbol ID */
    UINT32      i;

    /*
     * go through each block of the object, initialize all the structures
     * and create repair symbols.
     */
#ifdef WIN32
    QueryPerformanceCounter(&tv0);
    OF_PRINT(("encoding_start=%lI64f\n", (double)tv0.QuadPart / (double)freq.QuadPart))
#else
    gettimeofday(&tv0, NULL);
    OF_PRINT(("encoding_start=%ld.%ld\n", tv0.tv_sec, tv0.tv_usec))
#endif
    for (sbn = 0, blk = blk_cb_tab; sbn < tot_nb_blocks; sbn++, blk++) {
        k = blk->k;
        n = blk->n;
        /* don't forget to initialize the encoding symbol tab, used by the
         * FEC codec during encoding, since we cannot use the orig_symb table
         * where the source/repair symbols of a block are not sequential :-( */
        for (esi = 0; esi < k; esi++) {
            encoding_symbols_tab[esi] = (void*)(orig_symb[blk->first_src_symbol_idx + esi]);
        }
        for (; esi < n; esi++) {
            encoding_symbols_tab[esi] = (void*)(orig_symb[blk->first_repair_symbol_idx + (esi - k)]);
        }
        /*
         * create the codec instance and initialize it accordingly.
         * The case of a parity check matrix given in a file is handled
         * differently...
         */
#ifdef OF_USE_LDPC_FROM_FILE_CODEC
        if (codec_id == OF_CODEC_LDPC_FROM_FILE_ADVANCED)
        {
            if (of_create_codec_instance(&ses, codec_id, OF_ENCODER, of_verbosity) != OF_STATUS_OK) {
                OF_PRINT_ERROR(("ERROR: of_create_codec_instance() failed for codec_id %d\n", codec_id))
                goto error;
            }
            of_ldpc_ff_parameters_t     params;
            params.encoding_symbol_length   = symbol_size;
            params.pchk_file        = ldpc_matrix_file_name;
            if (of_set_fec_parameters(ses, (of_parameters_t*)&params) != OF_STATUS_OK) {
                OF_PRINT_ERROR(("ERROR: of_set_fec_parameters() failed for codec_id %d\n", codec_id))
                goto error;
            }
            k = params.nb_source_symbols;
            n = params.nb_source_symbols + params.nb_repair_symbols;
        } else
#endif
        {
            ses = create_and_init_codec_instance(codec_id, OF_ENCODER, k, n, blk);
            if (ses == NULL) {
                OF_PRINT_ERROR(("ERROR: create_and_init_codec_instance() failed for codec_id %d/OF_ENCODER\n", codec_id))
                goto error;
            }
        }
        /*
         * perform encoding and finally release the FEC codec instance.
         */
        for (esi = k; esi < n; esi++) {
            if (of_build_repair_symbol(ses, encoding_symbols_tab, esi) != OF_STATUS_OK) {
                OF_PRINT_ERROR(("ERROR: of_build_repair_symbol() failed\n"))
                goto error;
            }
        }

//SEND THE PACKETS TO THE RECEIVE!!!
#ifdef WIN
  WORD wVersionRequested = MAKEWORD(1,1);       // Stuff for WSA functions
  WSADATA wsaData;                              // Stuff for WSA functions
#endif
  int                  server_s;        // Server socket descriptor
  struct sockaddr_in   server_addr;     // Server Internet address
  struct sockaddr_in   client_addr;     // Client Internet address..i.e //receiver
  struct in_addr       client_ip_addr;  // Client IP address
  int                  addr_len;        // Internet address length
  char                 out_buf[symbol_size];   // Output buffer for data
  char                 in_buf[symbol_size];    // Input buffer for data
  int                  retcode;         // Return code

#ifdef WIN
  // This stuff initializes winsock
  WSAStartup(wVersionRequested, &wsaData);
#endif


  // >>> Step #3 <<<
  // Now send the message to server.  The "+ 1" is for the end-of-string
  // delimiter

            printf("*** Start sending messages.. \n");   

   //n is number of symbols to sent -- repair + original..
int j= 0;
   for (j=0; j < n ; j++ ) 
       {
    //fprintf ("sending test..first char is %c and %c",(char*) ///encoding_symbols_tab[j]);
       retcode = sendto(client_s, (const void*) encoding_symbols_tab[j],  symbol_size, 0,
      (struct sockaddr *)&server_addr, sizeof(server_addr) );

      if (retcode < 0)
      {
        printf("*** ERROR - sendto() failed.. retcode is %d \n", retcode);
        exit(-1);
      }
      else
       printf("*** ERROR - sendto() successs \n");

       }

接收器的一些代码:

  // >>> Step #1 <<<
  // Create a socket
  //   - AF_INET is Address Family Internet and SOCK_DGRAM is datagram
  server_s = socket(AF_INET, SOCK_DGRAM, 0);
  if (server_s < 0)
  {
    printf("*** ERROR - socket() failed \n");
    exit(-1);
  }
  else
    printf("*** Created server socket good. Server socket is %d \n", server_s);


  // >>> Step #2 <<<
  // Fill-in my socket's address information
  server_addr.sin_family = AF_INET;                 // Address family to use
  server_addr.sin_port = htons(PORT_NUM);           // Port number to use
  server_addr.sin_addr.s_addr = htonl(IP_ADDR);  // Listen on any IP address
    printf("***We have a server socket; and now we will try to bind it with the IP_ADDR-local host -- that we sent.. \n port nr %d & ip %s", PORT_NUM, IP_ADDR);

  retcode = bind(server_s, (struct sockaddr *)&server_addr,
    sizeof(server_addr));

  if (retcode < 0)
  {
    printf("*** ERROR - bind() failed \n");
    exit(-1);
  }
else
    printf("***Bind succeed.. \n");


//Storing all messages in in_buf -- here we will receive one; rest in code in decode-function.

 // >>> Step #3 <<<
  // Wait to receive a message from client
pthread_t thread1;
 int  iret1;
char *message1 = "Thread 1";

iret1 = pthread_create( &thread1, NULL,     waitToReceiveMessageFromClient, (void*) message1);

1 个答案:

答案 0 :(得分:1)

#include <stdlib.h>
#include <errno.h>
#include <strings.h>

...

retcode = some_system_call(...);
if (retcode == -1)
  {
    int err = errno;
    fprintf(stderr, "*** ERROR - bind() failed:%d(%s)\n"
      , err, strerror(err)
      );
    exit(EXIT_FAILURE);
  }

BTW:还有perror()