歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Unix知識 >> Unix基礎知識 >> UNIX網絡編程:UDP缺乏流量控制(改進版)

UNIX網絡編程:UDP缺乏流量控制(改進版)

日期:2017/3/3 14:55:21   编辑:Unix基礎知識

現在我們查看無任何流量控制的UDP對數據報傳輸的影響。首先我們把dg_cli函數修改為發送固定數目的數據報,並不再從標准輸入讀。如下,它寫2000個1400字節大小的UDP數據報給服務器。

客戶端程序cli.c:

#include <unistd.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  
#include <stdlib.h>  
#include <stdio.h>  
#include <errno.h>  
#include <string.h>  
      
#define SERV_PORT 3333  
#define MAXLINE 1024  
#define ERR_EXIT(m) \
        do \
        { \
                perror(m); \
                exit(EXIT_FAILURE); \
        } while(0)  
      
typedef struct sockaddr SA;  
#define NDG     2000    /* datagrams to send */  
#define DGLEN   1400    /* length of each datagram */  
      
void dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)  
{  
    int     i;  
    char    sendline[DGLEN];  
      
    for (i = 0; i < NDG; i++) {  
        sendto(sockfd, sendline, DGLEN, 0, pservaddr, servlen);  
    }  
}  
      
int main(int argc, char **argv)  
{  
    int                 sockfd;  
    struct sockaddr_in  servaddr;  
      
    if (argc != 2)  
        ERR_EXIT("usage: udpcli <IPaddress>");  
      
    bzero(&servaddr, sizeof(servaddr));  
    servaddr.sin_family = AF_INET;  
    servaddr.sin_port = htons(SERV_PORT);  
    inet_pton(AF_INET, argv[1], &servaddr.sin_addr);  
      
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);  
      
    dg_cli(stdin, sockfd, (SA *) &servaddr, sizeof(servaddr));  
      
    exit(0);  
}

然後,我們把服務器程序修改為接受數據報並對其計數,並不再把數據報回射給客戶。如下為新的dg_echo函數。當我們用終端中斷鍵終止服務器時(相當於向它發送SIGINT信號),服務器會顯示所接收到數據報的數目並終止。

查看本欄目更多精彩內容:http://www.bianceng.cn/OS/unix/

服務器程序serv.c:

#include<stdio.h>  
#include<stdlib.h>  
#include<unistd.h>  
#include<errno.h>  
#include<sys/types.h>  
#include<sys/socket.h>  
#include<netinet/in.h>  
#include<string.h>  
#include <signal.h>  
      
#define SERV_PORT 3333  
#define MAXLINE 1024  
      
#define ERR_EXIT(m)  \
    do { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while (0)  
      
typedef struct sockaddr SA;  
static void recvfrom_int(int);  
static int  count;  
      
void dg_echo(int sockfd, SA *pcliaddr, socklen_t clilen)  
{  
    socklen_t   len;  
    char        mesg[MAXLINE];  
      
    signal(SIGINT, recvfrom_int);  
      
    for ( ; ; ) {  
        len = clilen;  
        recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len);  
      
        count++;  
    }  
}  
      
static void recvfrom_int(int signo)  
{  
    printf("\nreceived %d datagrams\n", count);  
    exit(0);  
}  
      
      
int main(int argc, char **argv)  
{  
    int                 sockfd;  
    struct sockaddr_in  servaddr, cliaddr;  
      
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);  
      
    bzero(&servaddr, sizeof(servaddr));  
    servaddr.sin_family      = AF_INET;  
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);  
    servaddr.sin_port        = htons(SERV_PORT);  
      
    bind(sockfd, (SA *) &servaddr, sizeof(servaddr));  
      
    dg_echo(sockfd, (SA *) &cliaddr, sizeof(cliaddr));  
}

如果客戶端運行在快速的主機,服務器運行在慢速的主機,一般會出現丟包現象。

UDP套接字接收緩沖區

由UDP給某個特定套接字排隊的UDP數據報數目受限於該套接字接收緩沖區的大小。我們可以使用SO_RCVBUF套接字選項修改該值。

修改服務器程序serv.c的函數dg_echo:

static void recvfrom_int(int);  
static int  count;  
      
void
dg_echo(int sockfd, SA *pcliaddr, socklen_t clilen)  
{  
    int         n;  
    socklen_t   len;  
    char        mesg[MAXLINE];  
      
    signal(SIGINT, recvfrom_int);  
      
    n = 220 * 1024;  
    setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n));  
      
    for ( ; ; ) {  
        len = clilen;  
        recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len);  
      
        count++;  
    }  
}  
      
static void
recvfrom_int(int signo)  
{  
    printf("\nreceived %d datagrams\n", count);  
    exit(0);  
}

作者:csdn博客 ctthuangcheng

查看本欄目更多精彩內容:http://www.bianceng.cn/OS/unix/

Copyright © Linux教程網 All Rights Reserved