六 基于UDP的服务器端/客户端

在更重视性能而非可靠性的情况下,UDP是一种很好的选择。


实现基于UDP的服务器端/客户端


UDP中的服务器端和客户端没有连接,因此每次传输数据都要添加目标地址信息。

UDP服务器端和客户端均只需1个套接字


服务器端:
    /* UDP回声服务器端uecho_server.c */  
    #include<stdio.h>  
    #include<stdlib.h>  
    #include<string.h>  
    #include<unistd.h>  
    #include<arpa/inet.h>  
    #include<sys/socket.h>  
      
    #define BUF_SIZE 30  
      
    void error_handling(char *message)  
    {  
        fputs(message,stderr);  
        fputc('\n',stderr);  
        exit(1);  
    }  
      
    int main(int argc,char *argv[])  
    {  
        int serv_sock;  
        char message[BUF_SIZE];  
      
        int str_len;  
      
        struct sockaddr_in serv_adr, clnt_adr;  
        socklen_t clnt_adr_sz;  
      
        if (argc != 2) {  
            printf("Usage : %s <port> \n",argv[0]);  
            exit(1);  
        }  
      
        serv_sock = socket(PF_INET,SOCK_DGRAM,0);               //创建UDP套接字  
        if (serv_sock == -1)  
            error_handling("UDP socket() error!");  
      
        memset(&serv_adr,0,sizeof(serv_adr));  
        serv_adr.sin_family = AF_INET;  
        serv_adr.sin_addr.s_addr = htonl(INADDR_ANY);  
        serv_adr.sin_port = htons(atoi(argv[1]));  
      
        if (bind(serv_sock,(struct sockaddr*) &serv_adr,sizeof(serv_adr)) == -1)  
            error_handling("bind() error!");  
          
        while(1) {  
            clnt_adr_sz = sizeof(clnt_adr);  
            str_len = recvfrom(serv_sock,message,BUF_SIZE,0,(struct sockaddr*) &clnt_adr,&clnt_adr_sz);  
            sendto(serv_sock,message,str_len,0,(struct sockaddr*) &clnt_adr,clnt_adr_sz);  
            //通过47行的函数调用同时获取数据传输端的地址,并将接受的数据传会该地址  
        }  
              
        close(serv_sock);  
        return 0;  
    }  
客户端:
    /* UDP回声客户端 */  
    #include<stdio.h>  
    #include<stdlib.h>  
    #include<string.h>  
    #include<unistd.h>  
    #include<arpa/inet.h>  
    #include<sys/socket.h>  
      
    #define BUF_SIZE 30  
      
    void error_handling(char *message)  
    {  
        fputs(message,stderr);  
        fputc('\n',stderr);  
        exit(1);  
    }  
      
    int main(int argc,char *argv[])  
    {  
        int sock;  
        char message[BUF_SIZE];  
        int str_len;  
        socklen_t adr_sz;  
      
        struct sockaddr_in serv_adr,from_adr;  
      
        if(argc != 3) {  
            printf("Usage : %s <IP> <port>\n",argv[0]);  
            exit(1);  
        }  
          
        sock = socket(PF_INET,SOCK_DGRAM,0);  
        if (sock == -1)  
            error_handling("socket() error!");  
      
        memset(&serv_adr,0,sizeof(serv_adr));  
        serv_adr.sin_family = AF_INET;  
        serv_adr.sin_addr.s_addr = inet_addr(argv[1]);  
        serv_adr.sin_port = htons(atoi(argv[2]));  
          
        while (1) {  
            fputs("Input message(Q to quit): ",stdout);  
            fgets(message,sizeof(message),stdin);  
      
            if (!strcmp(message,"q\n") || !strcmp(message,"Q\n"))       // 输入q/Q退出  
                break;  
      
            sendto(sock,message,strlen(message),0,(struct sockaddr*) &serv_adr,sizeof(serv_adr));     
            // 首次sendto函数时给相应套接字自动分配IP和端口,分配的地址一直保存到程序结束为止  
              
            adr_sz  = sizeof(from_adr);  
            str_len = recvfrom(sock,message,BUF_SIZE,0,(struct sockaddr*) &from_adr, &adr_sz);  
            message[str_len] = 0;  
            printf("Message from server: %s",message);  
        }  
      
        close(sock);  
        return 0;  
    }  

知识点:

调用sendto函数时自动分配IP和端口号。

要与同一主机进行长时间通信时,将UDP套接字变成已连接套接字会提高效率。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值