小言_互联网的博客

Linux网络编程基础:UDP程序实现

422人阅读  评论(0)

UDP通信特点

1)没有连接机制
2)没有应答机制
3)没有滑动窗口机制
所以是一种不可靠的通信机制

UDP编程模型

1)调用socket函数创建套接字文件描述符
2)如果要接收数据,那么要调用bind函数绑定自身的ip和端口
3)调用sendto函数发送数据(需要使用对方的ip和端口)
sendto函数
函数原型:

#include <sys/types.h>
#include <sys/socket.h>
 ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);

功能就是向目标ip和端口发送数据,成功:返回发送字节数,失败:返回 -1
函数参数:
sockfd:socket函数返回的套接字文件描述符
buf:存放要发送数据的应用缓存
len:应用缓存的大小
flags:一般写0,表示为阻塞发送
dest_addr:存放目标ip和端口
addrlen:前一个变量的大小
4)调用recvfrom函数接收数据(需要使用对方的ip和端口)
recvfrom函数
函数原型:

#include <sys/types.h>
#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);

功能就是接收对方的数据
函数参数:
sockfd:用于通信的套接字文件描述符
buf:指向要存放获取数据的结构体变量
len:存放数据的变量的大小
flags:一般设置为0
src_addr:可以设置为指向一个存放对方ip和端口的结构体的指针,也可以设置为NULL
addrlen:存放上一个数据的大小的变量的指针,也可以设置为NULL

示例:

编写A程序,B程序,让两个程序通过UDP进行通信
A程序

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <signal.h>

int sockfd = -1;   //全局变量套接字文件
struct sockaddr_in peeraddr = {0};  //全局变量用于存放对方对方的ip和端口

struct data{   //用户自定义要传输或接收的数据结构
        unsigned int speed;
        unsigned int accel;
        unsigned int brake;
};
void print_err(char* str,int line,int err_no)  //报错函数
{
    printf("%d %s: %s\n",line,str,strerror(err_no));
    exit(-1);
}

void* pth_fun(void* pth_arg)  //次线程,用于接收数据
{
        struct data car_data2 = {0};  //接收数据的结构体变量
        int ret = 0;
        int peeraddr_size = 0;  //存放对方ip和端口的结构的大小
        while(1)
        {
                peeraddr_size = sizeof(peeraddr);
                bzero(&car_data2,sizeof(car_data2));  //清空结构体
                ret = recvfrom(sockfd,(void*)&car_data2,sizeof(car_data2),0,(struct sockaddr*)&peeraddr,&peeraddr_size);
                if(ret == -1)  print_err("recvfrom fail",__LINE__,errno);
                else if(ret>0)  //打印对方的ip和端口以及接收的数据
                {
                        printf("peeraddr ip:%s\n",inet_ntoa(peeraddr.sin_addr));
                        printf("peeraddr port:%d\n",ntohs(peeraddr.sin_port));
                        printf("car_speed = %d\n",ntohl(car_data2.speed));
                        printf("car_accel = %d\n",ntohl(car_data2.accel));
                        printf("car_brake = %d\n",ntohl(car_data2.brake));
                }
        }
        return NULL;
}

int main(int argc,char** argv)  //命令行输入对方的ip和端口
{
        if(argc != 3)
        {
                printf("./UDP_A peer_ip peer_port\n");
                exit(-1);
        }
        int ret = -1;
        //创建套接字文件
        sockfd = socket(PF_INET,SOCK_DGRAM,0);
        if(sockfd == -1) print_err("socket fail",__LINE__,errno);
        //绑定套接字文件与自身的ip和端口,用于接收数据
        struct sockaddr_in myaddr;
        myaddr.sin_family = AF_INET;
        myaddr.sin_port   = htons(8001);
        myaddr.sin_addr.s_addr = inet_addr("192.168.239.129");
        ret = bind(sockfd,(struct sockaddr *)&myaddr,sizeof(myaddr));
        if(ret == -1)  print_err("bind fail",__LINE__,errno);
        //创建次线程
        pthread_t tid;
        ret = pthread_create(&tid,NULL,pth_fun,NULL);
        if(ret != 0)  print_err("pthread_create fail",__LINE__,ret);
        //发送数据
        struct data car_data = {0};
        int tmp;
        while(1)
        {
                bzero(&car_data,sizeof(car_data));  //清空数据结构
                //填充数据结构
                printf("input car speed:\n");
                scanf("%d",&tmp);
                car_data.speed = htonl(tmp);

                printf("input car accel:\n");
                scanf("%d",&tmp);
                car_data.accel = htonl(tmp);

                printf("input car brake:\n");
                scanf("%d",&tmp);
                car_data.brake = htonl(tmp);
                //封入对方ip和端口
                peeraddr.sin_family = AF_INET;
                peeraddr.sin_port   = htons(atoi(argv[2]));
                peeraddr.sin_addr.s_addr = inet_addr(argv[1]);

                ret = sendto(sockfd,(void*)&car_data,sizeof(car_data),0,(struct sockaddr *)&peeraddr,sizeof(peeraddr));
                if(ret == -1)  print_err("sendto fail",__LINE__,errno);
        }
        return 0;
}

B程序:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <signal.h>

int sockfd = -1;
struct sockaddr_in peeraddr = {0};

struct data{
        unsigned int speed;
        unsigned int accel;
        unsigned int brake;
};

void print_err(char* str,int line,int err_no)
{
    printf("%d %s: %s\n",line,str,strerror(err_no));
    exit(-1);
}

void* pth_fun(void* pth_arg)
{
        struct data car_data2 = {0};
        int ret = 0;
        int peeraddr_size = 0;
        while(1)
        {
                peeraddr_size = sizeof(peeraddr);
                bzero(&car_data2,sizeof(car_data2));
                ret = recvfrom(sockfd,(void*)&car_data2,sizeof(car_data2),0,(struct sockaddr*)&peeraddr,&peeraddr_size);
                if(ret == -1)  print_err("recvfrom fail",__LINE__,errno);
                else if(ret>0)
                {
                        printf("peeraddr ip:%s\n",inet_ntoa(peeraddr.sin_addr));
                        printf("peeraddr port:%d\n",ntohs(peeraddr.sin_port));
                        printf("car_speed = %d\n",ntohl(car_data2.speed));
                        printf("car_accel = %d\n",ntohl(car_data2.accel));
                        printf("car_brake = %d\n",ntohl(car_data2.brake));
                }
        }
        return NULL;
}

int main(int argc,char** argv)
{
        if(argc != 3)
        {
                printf("./UDP_A peer_ip peer_port\n");
                exit(-1);
        }
        int ret = -1;
        sockfd = socket(PF_INET,SOCK_DGRAM,0);
        if(sockfd == -1) print_err("socket fail",__LINE__,errno);

        struct sockaddr_in myaddr;
        myaddr.sin_family = AF_INET;
        myaddr.sin_port   = htons(5001);
        myaddr.sin_addr.s_addr = inet_addr("192.168.239.128");
        ret = bind(sockfd,(struct sockaddr *)&myaddr,sizeof(myaddr));
        if(ret == -1)  print_err("bind fail",__LINE__,errno);

        pthread_t tid;
        ret = pthread_create(&tid,NULL,pth_fun,NULL);
        if(ret != 0)  print_err("pthread_create fail",__LINE__,ret);

        struct data car_data = {0};
        int tmp;
        while(1)
        {
                bzero(&car_data,sizeof(car_data));
                printf("input car speed:\n");
                scanf("%d",&tmp);
                car_data.speed = htonl(tmp);

                printf("input car accel:\n");
                scanf("%d",&tmp);
                car_data.accel = htonl(tmp);

                printf("input car brake:\n");
                scanf("%d",&tmp);
                car_data.brake = htonl(tmp);

                ret = sendto(sockfd,(void*)&car_data,sizeof(car_data),0,(struct sockaddr*)&peeraddr,sizeof(peeraddr));
                if(ret == -1)  print_err("sendto fail",__LINE__,errno);
        }          
        return 0;
}

转载:https://blog.csdn.net/weixin_45644911/article/details/104474812
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场