2013-01-02 77 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协议都限制数据报大小。

相关问题