嵌入式Linux网络编程,UDP循环服务器,sendto(),recvfrom()

2019-07-13 04:41发布

文章目录

在这里插入图片描述

1,UDP循环服务器模型:

socket(...); bind(...); while(1){ recvfrom(...); process(...); sendto(...); }

2,UDP的使用场景

  1. 实时的音视频传输
  2. DNS的域名解析

3,UDP数据发送和接受sendto()、recvfrom()

ssize_t sendto(int socket, void *message, size_t length, int flags, struct sockaddr *dest_addr, socklen_t dest_len); ssize_t recvfrom(int socket, void *buffer, size_t length, int flags, struct sockaddr *address, socklen_t *address_len);
这两个函数一般在使用UDP协议时使用

4,UDP循环服务器示例(可同时连接多个客户端)

4.1,头文件 net.h

#ifndef __NET_H__ #define __NET_H__ #include #include #include #include #include #include #include #include #include //#define SERV_IP_ADDR "192.168.31.100" #define SERV_PORT 5005 //#define BACKLOG 5 #define QUIT_STR "quite" #endif

4.2,客户端代码client.c

/* UDP demo */ /*./client serv_ip serv_port */ #include "net.h" void usage(char *s) { printf("this is a UDP demo! "); printf("Usage: %s ",s); printf(" serv_ip: UDP server ip address "); printf(" serv_port: UDP server port(>5000) "); } int main(int argc, const char *argv[]) { int fd; short port; struct sockaddr_in sin; if(argc != 3) { usage((char *)argv[0]); exit(1); } if((port = atoi(argv[2])) < 5000) { usage((char *)argv[0]); exit(1); } /* 1 创建socket fd */ if((fd = socket(AF_INET,SOCK_DGRAM,0)) < 0)//UDP编程 { perror("socket"); exit(-1); } /* 2 连接服务器 */ /* 2.1 填充struct sockaddr_in结构体变量*/ bzero(&sin,sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(port);//转为网络字节序端口号 #if 0 #else if(inet_pton(AF_INET,argv[1],(void *)&sin.sin_addr.s_addr) < 0) { perror("inet_pton"); goto _error1; } #endif printf("UDP client starting ...... OK! "); /* 3 读写*/ char buf[BUFSIZ]; while(1) { fprintf(stderr,"Please input the string to server:"); bzero(buf,BUFSIZ); if(fgets(buf,BUFSIZ-1,stdin) == NULL) { perror("fgets"); continue; } sendto(fd,buf,strlen(buf),0,(struct sockaddr *)&sin,sizeof(sin)); if(strncasecmp(buf,QUIT_STR,strlen(QUIT_STR)) == 0) { printf("client is existed! "); break; } } _error1: close(fd); return 0; }

4.3,服务器端代码server.c

#include "net.h" int main(int argc, const char *argv[]) { int fd; struct sockaddr_in sin; /* 1 创建socket fd */ if((fd = socket(AF_INET,SOCK_DGRAM,0)) < 0)//UDP编程,套接字类型为SOCK_DGRAM { perror("socket"); exit(-1); } /* 2 允许绑定地址快速重用 */ int b_reuse = 1; setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&b_reuse,sizeof(int)); /* 3 绑定 */ /* 3.1 填充struct sockaddr_in 结构体变量*/ bzero(&sin,sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(SERV_PORT); #if 1 /* 让服务器可以绑定在任意的IP上*/ sin.sin_addr.s_addr = htonl(INADDR_ANY); #else if(inet_pton(AF_INET,SERV_IP_ADDR,(void *)&sin.sin_addr.s_addr) < 0) { perror("inet_pton"); goto _error1; } #endif /* 3.2 绑定*/ if(bind(fd,(struct sockaddr *)&sin,sizeof(sin))) { perror("bind"); goto _error1; } printf("UDP server starting .... OK! "); char buf[BUFSIZ]; struct sockaddr_in cin; socklen_t addrlen = sizeof(cin); while(1) { /* 让系统自动获取客户端的信息*/ bzero(buf,BUFSIZ); if(recvfrom(fd,buf,BUFSIZ-1,0,(struct sockaddr *)&cin,&addrlen) < 0) { perror("recvfrom"); continue ; } char cin_ipv4_addr[16]; if(inet_ntop(AF_INET,&cin.sin_addr.s_addr,cin_ipv4_addr,sizeof(cin_ipv4_addr)) < 0) { perror("inet_ntop"); goto _error1; } printf("Receive from (%s:%d),Data: %s",cin_ipv4_addr,ntohs(cin.sin_port),buf); if(strncasecmp(buf,QUIT_STR,strlen(QUIT_STR)) == 0) { printf("client (%s:%d) is existing! ",cin_ipv4_addr,ntohs(cin.sin_port)); } } _error1: close(fd); return 0; }