zoukankan      html  css  js  c++  java
  • UDP套接口编程

    常用的UDP实现的程序:DNS域名系统,NFS网络文件系统,SNMP简单网络管理协议

    ssize_t recvfrom(int sockfd,void *buff,size_t nbytes,int flags,struct sockaddr * from,socklen_t *addrlen);
    ssize_t sendto(int sockfd,void *buff,size_t nbytes,int flags,struct sockaddr * to,socklen_t addrlen);
    sockfd:描述字
    buff:缓冲区指针
    nbytes 读写字节数
     
     UDP服务器端
    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));
    }
     
    void dg_echo(int sockfd,SA *pcliaddr,socklen_t clilen){
    int n;
    socklen_t len;
    char mesg[MAXLINE];
    for(;;){
        len = clilen;
        n = Recvfrom(sockfd,mesg,MAXLINE,0,pcliaddr,&len); //读一个到达的数据包
        Sendto(sockfd,mesg,n,0,pcliaddr,len); //发送回给客户机
    }
    }
    SOCK_DGRAM:UDP套接口
     
    1 函数不能终止
    2 服务器是迭代服务器,没有fork调用,单一服务器进程处理所有客户。
     
     
    UDP客户机程序:
    int main(int argc,char ** argv){
    int sockfd;
    struct sockaddr_t servaddr;
    if(argc != 2)
        err_quit("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);
    }
    void dg_cli(FILE *fp,int sockfd,const SA *pservaddr,socklen_t servlen){
    int n;
    char sendline[MAXLINE],recvline[MAXLINE+1];
    while(Fgets(sendline,MAXLINE,fp) != NULL){ //从标准输入读一行
        Sendto(sockfd,sendline,strlen(sendline),0,pservaddr,servlen); //使用sendto发送给服务器
        n = Recvfrom(sockfd,recvline,MAXLINE,0,NULL,NULL); //使用recvfrom接收服务器回射,NULL无视目标主机
        recvline[n] = 0; 
        Fputs(recvline,stdout); //fputs输出回射行到标准输出
    }
    }
    改进的dg_cli
    void dg_cli(FILE *fp,int sockfd,const SA * pservaddr,socklen_t servlen){
    int n;
    char sendline[MAXLINE],recvline[MAXLINE+1];
    socklen_t len;
    struct sockaddr *preply_addr;
    preply_addr = Malloc(servlen);
    while(Fgets(sendline,MAXLINE,fp)!= NULL ){
        Sendto(sockfd,sendline,strlen(sendline),0,pservaddr,servlen);
        len = servlen;
        n = Recvfrom(sockfd,recvline,MAXLINE,0,preply_addr,&len);
        if(len != servlen || memcpy(pservaddr,preply_addr,len) != 0){
            printf("reply from %s (ignored)
    ");
                        Sock_ntop(preply_addr,len);
            continue;
        }
        recvline[n] = 0;
        Fputs(recvline,stdout);
    }
    }
    解决办法:
    1 给定由recvfrom返回的IP,在DNS中查找服务器验证
    2 服务器配置每个IP地址创建套接口,捆绑IP地址此套接口,
     
     
    仅在进程已将UDP套接口连接到确切的对方后,这些一步错误才返回给进程。
     
    已连接的UDP套接口上调用connect达到下面两个目的:
    1 指定IP地址和端口号
    2 断开套接口
     
    使用connect连接后再调用read write
    void dg_cli(FILE *fp,int sockfd,const SA * pservaddr,socklen_t servlen){
        int n;
        char sendline[MAXLINE],recvline[MAXLINE+1];
        Connect(sockfd,(SA *)pservaddr,servlen);
        while(Fgets(sendline,MAXLINE,fp)!= NULL){
            Write(sockfd,sendline,strlen(sendline));
            n=Read(sockfd,recvline,MAXLINE);
            recvline[n] = 0;
            Fputs(recvline,stdout);
        }
    }
    对发送的UDP进行统计:
    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("
    received %d datagrams
    ",count);
        exit(0);
    }
     
    UDP与TCP的服务器复用:
    int main(int argc,char ** argv){
    int listenfd,connfd,updfd,nready,maxfdp1;
    char mesg[MAXLINE];
    pid_t childpid;
    fd_set rset;
    ssize_t n;
    socklen_t len;
    const int on = 1;
    struct sockaddr_in cliaddr,servaddr;
    void sig_child(int);
     
    listenfd = Socket(AF_INET,SOCKSTREAM,0);
    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family=AF_INET;
    servaddr.sin_addr.s_add=htonl(INADDR_ANY);
    servaddr.sin_port=htons(SERV_PORT);
    Setsockopt(listenfd,SOL_SOCKET,SO_RESSEADDR,&on,sizeof(on));
    Bind(listenfd,(SA *)&servaddr,sizeof(servaddr));
    Listen(listenfd,LISTENQ);
     
    updfd=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(udpfd,(SA *)&servaddr,sizeof(servaddr));
     
    Signal(SIGCHLD,sig_chld);
    FD_ZERO(&rset);
    maxfdp1=max(listenfd,udpfd)+1;
    for(;;){
        FD_SET(listenfd,&rset);
        FD_SET(udpfd,&rset);
        if((nready=select(maxfdp1,&rset,NULL,NULL,NULL,NULL))<0){
            if(errno==EINTR)
                continue;
            else
                err_sys("select error");
        }
        if(FD_ISSET(listenfd,&rset)){
            len = sizeof(cliaddr);
            connfd=Accept(listenfd,(SA *)&cliaddr,&len);
            if((childpid=Fork())==0){
                Close(listenfd);
                str_echo(connfd);
                exit(0);
            }
            Close(connfd);
        }
        if(FD_ISSET(udpfd,&rset)){
            len=sizeof(cliaddr);
            n=Recvfrom(udpfd,mesg,MAXLINE,0,(SA *)&cliaddr,&len);
            Sendto(udpfd,mesg,n,0,(SA *)&cliaddr,len);
        }
    }
    }
  • 相关阅读:
    基础知识
    显示功能
    监听器
    检测session是否为空
    W7-Web服务器[JavaWeb]
    D9-哈希表[Java数据结构和算法]
    D8-查找算法[Java数据结构和算法]
    D7-排序算法(三)[Java数据结构和算法]
    W6-junit、泛型、枚举、增强for、可变参数、反射[JavaWeb]
    D6-排序算法(二)[Java数据结构和算法]
  • 原文地址:https://www.cnblogs.com/xing901022/p/3528192.html
Copyright © 2011-2022 走看看