美文网首页
基于UDP协议的服务器/客户端编程

基于UDP协议的服务器/客户端编程

作者: arkliu | 来源:发表于2022-12-03 08:17 被阅读0次

UDP客户端服务器编程模型

image.png

发送数据相关api

#include <sys/types.h>
#include <sys/socket.h>

ssize_t send(int sockfd, const void *buf, size_t len, int flags);
成功返回发送字节数,失败返回-1

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
              const struct sockaddr *dest_addr, socklen_t addrlen);
成功返回发送字节数,失败返回-1

ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
成功返回发送字节数,失败返回-1

接收数据相关api

#include <sys/types.h>
#include <sys/socket.h>

ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                struct sockaddr *src_addr, socklen_t *addrlen);
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

返回消息的字节数,无消息返回0,出错返回-1

基于UDP协议的服务器

接收客户端发送的数据,并发送当前时间给客户端

#include<sys/socket.h>
#include <netdb.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<signal.h>
#include<time.h>
#include<arpa/inet.h>

int sockfd;

void sig_handler(int sig_no) {
    if(sig_no == SIGINT) {
        printf("server close\n");
        close(sockfd);
        exit(1);
    }
}

//输出客户端的信息
void out_addr(struct sockaddr_in *clientaddr) {
    char ip[16];
    int port;
    memset(ip, 0, sizeof(ip));
    inet_ntop(AF_INET,
            &clientaddr->sin_addr.s_addr,ip,sizeof(ip));
    port = ntohs(clientaddr->sin_port);
    printf("client: %s(%d\n", ip, port);
}

// 和客户端进行通信
void do_service() {
    struct sockaddr_in clientaddr;
    socklen_t len = sizeof(clientaddr);
    char buffer[1024];
    memset(buffer, 0 , sizeof(buffer));
    // 接收客户端的数据报文
    if(recvfrom(sockfd, buffer, sizeof(buffer), 0,
                (struct sockaddr*)&clientaddr, &len) < 0) {
        perror("recvfrom error");
    } else {
        out_addr(&clientaddr);
        printf("client send info:%s\n", buffer);
        //向客户端发送数据报文
        long int t = time(NULL);
        char *ptr = ctime(&t);

        size_t size = strlen(ptr) * sizeof(char);
        if(sendto(sockfd, ptr, size, 0, 
            (struct sockaddr*)&clientaddr, len) <0) {
            perror("sendto error");
        }
    }
}

int main(int argc, char* argv[]) {
    if (argc < 2){
        printf("usage:%s #port\n",argv[0]);
        exit(1);
    }
    
    if (signal(SIGINT, sig_handler) == SIG_ERR){
        perror("signale sigint error");
        exit(1);
    }
    /*步骤1:创建socket*/
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(sockfd < 0) {
        perror("socket error");
        exit(1);
    }
    int ret;
    int opt = 1;  
    //设置套接字选项
    if((ret = setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR, &opt,sizeof(opt))) < 0) {
        perror("setsockopt error");
        exit(1);
    }

    /*步骤2:调用bind函数对socket和地址进行绑定*/
    struct sockaddr_in serveradr;
    memset(&serveradr, 0, sizeof(serveradr));
    serveradr.sin_family = AF_INET;
    serveradr.sin_port = htons(atoi(argv[1]));
    serveradr.sin_addr.s_addr = INADDR_ANY;
    if(bind(sockfd, (struct sockaddr*)&serveradr,sizeof(serveradr)) < 0) {
        perror("bind error");
        exit(1);
    }
    /*步骤3:和客户端进行双向的数据通信*/
    while(1) {
        do_service();
    }
    return 0;
}

基于UDP协议的客户端

#include<sys/socket.h>
#include <netdb.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<signal.h>
#include<time.h>
#include<arpa/inet.h>

int main(int argc, char* argv[]) {

    if (argc < 3){
        printf("usage:%s ip port\n",argv[0]);
        exit(1);
    }
    /*步骤1:创建socket*/
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0){
        perror("socket error");
        exit(1);
    }

    /*步骤2:调用recvfrom和sendto等函数和服务器进行双向通信*/
    struct sockaddr_in serveraddr;
    memset(&serveraddr, 0 , sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(atoi(argv[2])); // port
    inet_pton(AF_INET, argv[1],
                &serveraddr.sin_addr.s_addr); // ip

    char buffer[1024] = "hello world";
    if(sendto(sockfd, buffer, sizeof(buffer), 0,
                (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0){
        perror("sendto error");
        exit(1);
    }else{
        // 接收服务器端发送的数据报文
        memset(buffer, 0, sizeof(buffer));
        size_t size;
        if((size = recv(sockfd,buffer, sizeof(buffer), 0)) < 0) {
            perror("recv error");
            exit(1);
        } else {
            printf("%s", buffer);
        }
    }         
    return 0;
}

服务器:


image.png

客户端:


image.png

相关文章

网友评论

      本文标题:基于UDP协议的服务器/客户端编程

      本文链接:https://www.haomeiwen.com/subject/ctqsfdtx.html