基于UDP的C/S网络通信模型

无连接套接字是一种实现绑定到无连接协议(UDP协议)的套接字,基于无连接套接字的C/S通信模型如下图。

1、UDP服务器端算法的实现流程

(1) UDP服务器端算法的步骤描述

① 调用socket()函数创建服务器端无连接套接字。

② 调用bind()函数将套接字绑定到本机的一个可用的端点地址。

③ 调用recvfrom()函数从套接字接收来自远程客户端的数据并存入到缓冲区中,同时获得远程客户的套接字端点地址并保存。

④ 基于保存的远程客户的套接字端点地址,调用sendto()函数将缓冲区中的数据从套接字发送给该远程客户。

⑤ 与客户交互完毕,调用close()函数将套接字关闭,释放所占用的系统资源。

(2) 代码实现

/*server.c*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define MAXLINE 80
#define SERV_PORT 8000

int main()
{
    struct sockaddr_in servaddr, cliaddr;
    socklen_t cliaddr_len;
    int sockfd;
    char buf[MAXLINE];
    char str[INET_ADDRSTRLEN];
    int i, n;

    /*打开一个网络通讯端口,分配一个文件描述符sockfd*/
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    bzero(&servaddr, sizeof(servaddr));//初始化为空
    servaddr.sin_family = AF_INET;//地址采用IPv4地址
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//地址从主机字节顺序转换成网络字节顺序
    servaddr.sin_port = htons(SERV_PORT);//端口号从主机字节顺序转换成网络字节顺序
    /*将文件描述符sockfd和服务器地址绑定*/
    bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

    printf("等待连接...\n");
    while(1){
        cliaddr_len = sizeof(cliaddr);
        /*接收client端传过来的的字符串,写入buf*/
        n = recvfrom(sockfd, buf, MAXLINE, 0, (struct sockaddr*)&cliaddr, &cliaddr_len);
        if(n == -1){
            printf("recvfrom error");
        }
        /*打印客户端IP及端口*/
        printf("接收到来自地址为 %s 端口号为 %d 的数据\n", 
                (char*)inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
                ntohs(cliaddr.sin_port));
        /*小写转为大写*/        
        for(i = 0; i<n; i++){
            buf[i] = toupper(buf[i]);
        }
        /*把数据发送给客户端*/
        n = sendto(sockfd, buf, n, 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr));
        if (n == -1){
            printf("sendto error\n");
        }
    }

    return 0;
}

2、UDP客户端算法的实现流程

(1) UDP客户端算法的步骤描述

① 调用socket()函数创建客户端无连接套接字。

② 找到期望与之通信的远程服务器ip地址和协议端口号;然后再调用sendto()函数将缓冲区中的数据从套接字发送给远程服务器。

③ 调用recvfrom()函数从套接字接收来自远程服务器端的数据并存入缓冲区中。

④ 与服务器交互完毕,调用close()函数将套接字关闭,释放所占用的系统资源。

(2) 代码实现

/*client.c*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define MAXLINE 80
#define SERV_PORT 8000

int main(int argc, char *argv[])
{
    struct sockaddr_in servaddr;
    int sockfd, n;
    char buf[MAXLINE];
    char str[INET_ADDRSTRLEN];
    socklen_t servaddr_len;
    /*打开一个网络通讯端口,分配一个文件描述符sockfd*/
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr); //将“点分十进制” -> “二进制整数”
    servaddr.sin_port = htons(SERV_PORT);//端口号从主机字节顺序转换成网络字节顺序

    while(fgets(buf, MAXLINE, stdin) != NULL){ //输入字符串
        /*发送给服务端*/
        n = sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr*)&servaddr, sizeof(servaddr));
        if(n == -1)
            printf("sebdto err\n");
        /*从服务端接收数据*/
        n = recvfrom(sockfd, buf, MAXLINE, 0, NULL, 0);
        if(n == -1)
            printf("recvfrom err\n");
        /*输出服务器处理后的数据*/
        write(STDOUT_FILENO, buf, n);
    }

    close(sockfd);
    return 0;
}

运行结果:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值