2013-01-02 76 views
1

我有兩臺機器,我希望他們兩個之間使用C編程語言下的套接字進行通信。Linux上的UDP套接字;發送成功但無法接收大緩衝區

我開發了兩個樣本代表雙方,但我注意到,如果它們小於特定數字,我可以成功發送數據。

我測試過但不起作用的尺寸是發送&接收2048字節,相反,對於其他較小的尺寸,例如258字節,1KByte它工作正常。

經過一番調查,我發現發送操作在接收時沒有錯誤,我什麼也沒有得到。

我檢查了兩臺機器上的發送和接收緩衝區大小,我猜測它們已經足夠了。

這裏是我的代碼的第一側:

/* UDP client in the internet domain */ 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <netdb.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 
#include <assert.h> 

#define BUFF_SIZE    1800 
#define MOBIPASS_L2_IP_ADDRESS "192.168.13.53" 
#define MOBIPASS_L2_PORT_NUM 12001 

#define BRIDGE_IP_ADDRESS  "192.168.13.30" 
#define BRIDGE_PORT_NUM   12000 

#define RESTRICT_SRC_DST_NUM  1 
#define TEN_MSEC     10000 

void error(const char *); 
void adjustSockParam (int sockFD); 

int main(int argc, char *argv[]) 
{ 
#if RESTRICT_SRC_DST_NUM 

    int bridge_sock_fd = -1, n =-1; 
    struct sockaddr_in server_mobipass, client_bridge; 
    char buffer[BUFF_SIZE]; 
    char* choice = NULL; 
    size_t size = 1; 

    /* create socket descriptor at client machine*/ 
    bridge_sock_fd= socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 
    if (bridge_sock_fd < 0) error("socket"); 

    /* ********************************************************* 
    * prepare source information of the socket file descriptor 
    * ********************************************************* 
    */ 
    client_bridge.sin_family = AF_INET; 
    client_bridge.sin_addr.s_addr=inet_addr(BRIDGE_IP_ADDRESS) ; 
    client_bridge.sin_port = htons(BRIDGE_PORT_NUM); 
    if(bind(bridge_sock_fd, (struct sockaddr *) &client_bridge, sizeof (client_bridge)) < 0) 
    { 
     error("bind"); 
    } 


    /* ********************************************************* 
    * prepare destination information of the socket file descriptor 
    * ********************************************************* 
    */ 
    server_mobipass.sin_family = AF_INET; 
    server_mobipass.sin_addr.s_addr=inet_addr(MOBIPASS_L2_IP_ADDRESS) ; 
    server_mobipass.sin_port = htons(MOBIPASS_L2_PORT_NUM); 
    if(connect(bridge_sock_fd, (struct sockaddr *) &server_mobipass, sizeof (server_mobipass)) < 0) { 
     error("connect"); 
    } 

    adjustSockParam(bridge_sock_fd); 
    do 
    { 
     printf("sending traffic?[y/n]\n"); 
     getline(&choice,&size,stdin); 
     if(*choice=='n') 
      break; 

     strncpy(buffer, 
        "Hello Mobipass, this is bridge :)\n", 
        sizeof(buffer)); 
     n = send(bridge_sock_fd, buffer, sizeof(buffer), MSG_CONFIRM ); 
     if(n < 0) 
     { 
      error("send"); 
     } 

     assert(n == sizeof(buffer)); 

     usleep(TEN_MSEC); 
     /*memset(buffer,0 , sizeof(buffer)); 

     if(recv(bridge_sock_fd, buffer, sizeof(buffer), 0) < 0) 
     { 
      error("recv"); 
     } 
     else 
     { 
      printf("Msg received from mobipass is:\n%s",buffer); 
     }*/ 


    }while(*choice == 'y' || *choice == 'Y'); 

    close(bridge_sock_fd); 

#else 
    int tx_sock, n, rx_sock; 
    unsigned int srv_length; 
    struct sockaddr_in server_mobipass, from, server_bridge; 
    char buffer[256]; 

    /* create socket descriptor at client machine*/ 
    tx_sock= socket(AF_INET, SOCK_DGRAM, 0); 
    if (tx_sock < 0) error("socket"); 

    srv_length=sizeof(struct sockaddr_in); 

    /*prepare server (peer entity) of UDP connection*/ 
    server_mobipass.sin_family = AF_INET; 
    server_mobipass.sin_addr.s_addr=inet_addr(MOBIPASS_L2_IP_ADDRESS) ; 
    server_mobipass.sin_port = htons(MOBIPASS_L2_PORT_NUM); 

    printf("Please enter the message: "); 
    bzero(buffer,256); 
    fgets(buffer,255,stdin); 

    n=sendto(tx_sock,buffer, 
      strlen(buffer),0,(const struct sockaddr *)&server_mobipass,srv_length); 
    if (n < 0) error("Sendto"); 

    rx_sock= socket(AF_INET, SOCK_DGRAM, 0); 
    if (rx_sock < 0) error("socket"); 

    server_bridge.sin_family = AF_INET; 
    server_bridge.sin_addr.s_addr = inet_addr(BRIDGE_IP_ADDRESS); 
    server_bridge.sin_port = htons(BRIDGE_PORT_NUM); 
    if (bind(rx_sock,(struct sockaddr *)&server_bridge,srv_length)<0) 
      error("binding"); 

    n = recvfrom(rx_sock,buffer,256,0,(struct sockaddr *)&from, &srv_length); 
    if (n < 0) error("recvfrom"); 

    /*print to stdout what have been received*/ 
    write(1,"Got an ack: ",12); 
    write(1,buffer,n); 





    /* close sockets */ 
    close(rx_sock); 
    close(tx_sock); 

#endif /* RESTRICT_SRC_DST_NUM */ 
    return 0; 
} 

void error(const char *msg) 
{ 
    perror(msg); 
    exit(0); 
} 

void adjustSockParam (int sockFD) 
{ 

    int option_value; 
    socklen_t option_len = sizeof(option_value); 

    /** Adjust Send Buffer Size**/ 
    if(getsockopt(sockFD, SOL_SOCKET, SO_SNDBUF, 
      &option_value, &option_len)< 0) 
    { 
     error("get Socket Option error:"); 
    } 
    printf("Initial SO_SNDBUF: option_len = %d option_value = %d\n",option_len,option_value); 

    /*option_value = 2048; 
    if(setsockopt(sockFD, SOL_SOCKET, SO_SNDBUF, 
      &option_value, option_len)< 0) 
    { 
     error("get Socket Option error:"); 
    } 

    if(getsockopt(sockFD, SOL_SOCKET, SO_SNDBUF, 
      &option_value, &option_len)< 0) 
    { 
     error("get Socket Option error:"); 
    } 
    printf("Final SO_SNDBUF: option_len = %d option_value = %d\n",option_len,option_value);*/ 

    /** Adjust Receiver Buffer Size **/ 
    if(getsockopt(sockFD, SOL_SOCKET, SO_RCVBUF, 
       &option_value, &option_len)< 0) 
     { 
      error("get Socket Option error:"); 
     } 
     printf("Initial SO_RCVBUF: option_len = %d option_value = %d\n",option_len,option_value); 
} 

這裏是我的代碼的第二側:

#include <sys/types.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <string.h> 
#include <netdb.h> 
#include <stdio.h> 
#include <assert.h> 

#define BUFF_SIZE    1800 
#define MOBIPASS_L2_IP_ADDRESS "192.168.13.53" 
#define MOBIPASS_L2_PORT_NUM 12001 

#define BRIDGE_IP_ADDRESS  "192.168.13.30" 
#define BRIDGE_PORT_NUM   12000 

#define DUMP      0 
#define ACT_AS_STRING    0 
#define RESTRICT_SRC_DST_NUM  1 
#define TEN_MSEC     10000 

#if DUMP 
    #define DUMP_BUFFER(buf,len)    \ 
    {           \ 
     int i;         \ 
     for(i = 0; i < len; i++)    \ 
      printf("buf[%d] = 0x%x",i,buf[i]); \ 
    } 
#else 
    #define DUMP_BUFFER(buf,len)  printf("received len=%d\n",len) 
#endif 

void adjustSockParam (int sockFD); 
void error(const char *msg) 
{ 
    perror(msg); 
    exit(0); 
} 

int main(int argc, char *argv[]) 
{ 
#if RESTRICT_SRC_DST_NUM 
    int mobipass_sock_fd = -1; 
    struct sockaddr_in server_mobipass, client_bridge; 
    char buffer[BUFF_SIZE]; 
    int recivedBytes=-1; 

    printf("size of buffer = %d\n",sizeof(buffer)); 
    /* create socket descriptor at client machine*/ 
    mobipass_sock_fd= socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 
    if (mobipass_sock_fd < 0) error("socket"); 

    /* ********************************************************* 
    * prepare source information of the socket file descriptor 
    * ********************************************************* 
    */ 
    client_bridge.sin_family = AF_INET; 
    client_bridge.sin_addr.s_addr=inet_addr(MOBIPASS_L2_IP_ADDRESS) ; 
    client_bridge.sin_port = htons(MOBIPASS_L2_PORT_NUM); 
    if(bind(mobipass_sock_fd, (struct sockaddr *) &client_bridge, sizeof (client_bridge)) < 0) 
    { 
     error("bind"); 
    } 


    /* ********************************************************* 
    * prepare destination information of the socket file descriptor 
    * ********************************************************* 
    */ 
    server_mobipass.sin_family = AF_INET; 
    server_mobipass.sin_addr.s_addr=inet_addr(BRIDGE_IP_ADDRESS) ; 
    server_mobipass.sin_port = htons(BRIDGE_PORT_NUM); 
    if(connect(mobipass_sock_fd, (struct sockaddr *) &server_mobipass, sizeof (server_mobipass)) < 0) { 
     error("connect"); 
    } 

    adjustSockParam(mobipass_sock_fd); 

    printf("waiting for message from bridge:\n"); 
    do{ 
     memset(buffer,0 , sizeof(buffer)); 
     recivedBytes = recv(mobipass_sock_fd, buffer, sizeof(buffer), 0); 
     if(recivedBytes < 0) 
     { 
      error("recv"); 
     } 
     else 
     { 
      assert(recivedBytes == sizeof(buffer)); 
      DUMP_BUFFER(buffer,recivedBytes); 
#if ACT_AS_STRING 
      printf("Msg received from bridge is:\n%s",buffer); 
#endif 
     } 
     usleep(TEN_MSEC); 
#if ACT_AS_STRING 
     strncpy(buffer, 
        "Hello Bridge, this is mobipass :)\n", 
        sizeof(buffer)); 
     if(send(mobipass_sock_fd, buffer, sizeof(buffer), 0) < 0) 
     { 
      error("send"); 
     } 
#endif 
    }while(1); 

    close(mobipass_sock_fd); 

#else 
    int tx_sock, n, rx_sock; 
    unsigned int srv_length; 
    socklen_t fromlen; 
    struct sockaddr_in server_mobipass, from, server_bridge; 
    char buf[1024]; 


    rx_sock=socket(AF_INET, SOCK_DGRAM, 0); 
    if (rx_sock < 0) error("Opening socket"); 
    else printf("Creating rx udp socket\n"); 

    srv_length = sizeof(server_mobipass); 
    bzero(&server_mobipass,srv_length); 

    server_mobipass.sin_family=AF_INET; 
    server_mobipass.sin_addr.s_addr=inet_addr(MOBIPASS_L2_IP_ADDRESS); 
    server_mobipass.sin_port=htons(MOBIPASS_L2_PORT_NUM); 

    if (bind(rx_sock,(struct sockaddr *)&server_mobipass,srv_length)<0) 
    error("binding"); 
    else 
    printf("Binding a socket to a server IP address\n"); 
    fromlen = sizeof(struct sockaddr_in); 

    tx_sock=socket(AF_INET, SOCK_DGRAM, 0); 
    if (tx_sock < 0) error("Opening socket"); 
    else printf("Creating tx udp socket\n"); 

    server_bridge.sin_family=AF_INET; 
    server_bridge.sin_addr.s_addr=inet_addr(BRIDGE_IP_ADDRESS); 
    server_bridge.sin_port=htons(BRIDGE_PORT_NUM); 

    while (1) 
    { 
    printf("waiting for a message from client side:\n"); 
    n = recvfrom(rx_sock,buf,1024,0,(struct sockaddr *)&from,&fromlen); 
    if (n < 0) error("recvfrom"); 

    write(1,"Message received from eNB machince:\n",36); 
    write(1,buf,n); 

    n = sendto(tx_sock,"hello eNB, I am mobipass\n",27, 
       0,(struct sockaddr *)&server_bridge,fromlen); 
    if (n < 0) error("sendto"); 
    } 

#endif 
    return 0; 
} 

void adjustSockParam (int sockFD) 
{ 

    int option_value; 
    socklen_t option_len = sizeof(option_value); 

    /** Adjust Send Buffer Size**/ 
    if(getsockopt(sockFD, SOL_SOCKET, SO_SNDBUF, 
      &option_value, &option_len)< 0) 
    { 
     error("get Socket Option error:"); 
    } 
    printf("Initial SO_SNDBUF: option_len = %d option_value = %d\n",option_len,option_value); 

/* option_value = 2048; 
    if(setsockopt(sockFD, SOL_SOCKET, SO_SNDBUF, 
      &option_value, option_len)< 0) 
    { 
     error("get Socket Option error:"); 
    } 

    if(getsockopt(sockFD, SOL_SOCKET, SO_SNDBUF, 
      &option_value, &option_len)< 0) 
    { 
     error("get Socket Option error:"); 
    } 
    printf("Final SO_SNDBUF: option_len = %d option_value = %d\n",option_len,option_value);*/ 

    /** Adjust Receiver Buffer Size **/ 
    if(getsockopt(sockFD, SOL_SOCKET, SO_RCVBUF, 
       &option_value, &option_len)< 0) 
     { 
      error("get Socket Option error:"); 
     } 
     printf("Initial SO_RCVBUF: option_len = %d option_value = %d\n",option_len,option_value); 
} 

這裏是關於第一側上的輸出:

Initial SO_SNDBUF: option_len = 4 option_value = 112640 
Initial SO_RCVBUF: option_len = 4 option_value = 112640 
sending traffic?[y/n] 
y 
sending traffic?[y/n] 
y 

這是第二面的輸出:

size of buffer = 1800 
Initial SO_SNDBUF: option_len = 4 option_value = 1048576 
Initial SO_RCVBUF: option_len = 4 option_value = 1048576 
waiting for message from bridge: 

我不知道我在做什麼錯在這裏。你有什麼建議嗎?

+0

機器是否位於同一網絡中?你可以在接收端做一個數據包捕獲嗎?這是非常可能的碎片不能通過。 – cnicutar

+0

嘗試發送更多數據時,您會更改哪些代碼部分?有一些硬編碼的值,如1800,1024和256。 –

回答

1

儘管UDP數據報包大小可能高達64K(16位數據長度字段),但通常的基礎數據鏈接技術 - 以太網 - 的幀大小爲1500字節。對於IP標頭,少於至少20個字節,少於8個字節的UDP標頭,僅留下1472字節用於UDP有效載荷,可以在沒有IP分段的情況下發送,這通常會導致類似於數據包剛剛被丟棄的問題。

正是出於這個原因,大多數基於UDP協議都限制數據報大小。

相關問題