唐山网站建设冀icp备,网址链接,金诚信矿业建设集团有限公司网站,中国国家人事人才培训网证书查询转自#xff1a;https://www.cnblogs.com/wangzhilei-src/p/15314315.html UDP是面向非连接的协议#xff0c;它不与对方建立连接#xff0c;而是直接把数据报发给对方。UDP无需建立类如三次握手的连接#xff0c;使得通信效率很高。因此UDP适用于一次传输数据量很少、对可…转自https://www.cnblogs.com/wangzhilei-src/p/15314315.html UDP是面向非连接的协议它不与对方建立连接而是直接把数据报发给对方。UDP无需建立类如三次握手的连接使得通信效率很高。因此UDP适用于一次传输数据量很少、对可靠性要求不高的或对实时性要求高的应用场景 sendto
int sendto(int s, const void *buf, int len, unsigned int flags, const struct sockaddr *to, int tolen);返回值 成功则返回实际传送出去的字符数失败返回-1错误原因会存于errno 中。 参数说明 s socket描述符 buf UDP数据报缓存区包含待发送数据 len UDP数据报的长度 flags调用方式标志位一般设置为0 to 指向接收数据的主机地址信息的结构体sockaddr_in需类型转换 tolento所指结构体的长度 recvfrom()
int recvfrom(int s, void *buf, int len, unsigned int flags,struct sockaddr *from, int *fromlen);返回值 成功则返回实际接收到的字符数失败返回-1错误原因会存于errno 中。 参数 s socket描述符 buf UDP数据报缓存区包含所接收的数据 len 缓冲区长度。 flags 调用操作方式一般设置为0。 from 指向发送数据的客户端地址信息的结构体sockaddr_in需类型转换 fromlen指针指向from结构体长度值 UDP点对点
udp_server.c#include stdio.h
#include stdlib.h
#include string.h
#include sys/socket.h
#include netinet/in.h
#include sys/types.hconst int SERV_PORT6000;
const int MAXLINE2048;void dg_echo(int sockfd,struct sockaddr *pcliaddr,socklen_t clilen)
{int n;socklen_t len;char mesg[MAXLINE];for (;;){lenclilen;if ((nrecvfrom(sockfd,mesg,MAXLINE,0,pcliaddr,len))0){perror(recvfrom error);exit(1);}fputs(mesg, stdout);if((nsendto(sockfd,mesg,n,0,pcliaddr,len))0){perror(sendto error);exit(1);}}}
int main(int argc,char **argv)
{int sockfd;struct sockaddr_in servaddr,cliaddr;bzero(servaddr, sizeof(servaddr));servaddr.sin_family AF_INET;servaddr.sin_addr.s_addr INADDR_ANY;servaddr.sin_port htons(SERV_PORT);if ((sockfdsocket(AF_INET,SOCK_DGRAM,0))0){printf(SOCKET ERROR);exit(1);}if (bind(sockfd,(struct sockaddr *)servaddr,sizeof(servaddr))){perror(bind error);exit(1);}dg_echo(sockfd,(struct sockaddr *)cliaddr,sizeof(cliaddr));
}udp_client.c#include stdio.h
#include stdlib.h
#include string.h
#include sys/socket.h
#include netinet/in.h
#include arpa/inet.hconst int SERV_PORT 6000;const int MAXLINE 2048;void dg_cli(FILE *fp, int sockfd, const struct sockaddr *pservaddr, socklen_t servlen)
{int n;char sendline[MAXLINE], recvline[MAXLINE 1];while (fgets(sendline, MAXLINE, fp) ! NULL){if (sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen) 0){perror(sendto error);exit(1);}if ((n recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL)) 0){perror(recvfrom error);exit(1);}recvline[n] \0;fputs(recvline, stdout);}
}
int main(int argc, char **argv)
{int sockfd;struct sockaddr_in servaddr;if (argc ! 2){perror(usage:tcpcli);exit(1);}//1.创建套接字if ((sockfd socket(AF_INET, SOCK_DGRAM, 0)) -1){perror(socket error);exit(1);}//2.设置链接服务器地址结体bzero(servaddr, sizeof(servaddr));servaddr.sin_family AF_INET;servaddr.sin_port htons(SERV_PORT);if ((inet_pton(AF_INET, argv[1], servaddr.sin_addr)) 0){printf(inet_pton error for %s\n, argv[1]);exit(1);}if ((sockfd socket(AF_INET, SOCK_DGRAM, 0)) 0){perror(socket error);}dg_cli(stdin, sockfd, (struct sockaddr *)servaddr, sizeof(servaddr));exit(0);
}UDP广播数据包 路由器不转发广播数据包 交换机转发广播数据包 广播只能在一个广播域(局域网)中传播而不能跨网段传播 arp协议 MACFF:FF:FF:FF:FF:FFIP:10.0.0.0/8--10.255.255.255 广播地址 192.168.199.1/24--192.168.199.255 广播地址 192.168.0.1/30--192.168.0.3(广播地址)(192.168.0.0回环地址)
UDP广播递送规则
如果未设置BLOADCASE选项不递送如果bind端口不匹配不递送该套接口必须bind一个广播地址或绑定INADDR_ANY如果udp调用了connect那么源地址和源端口不匹配也不递送否则递送ifconfig可disable网卡的BROADCAST标志让其不能接受以太网广播ioctl的SIOCSIFFLAGS方法去掉接口的标志IFF_BROADCAST使之不能接受以太网广播。
recv.c#include ../config.hint main(int argc,char **argv)
{struct sockaddr_in s_addr;struct sockaddr_in c_addr;int sock;socklen_t addr_len;int len;char buff[128];if ((socksocket(AF_INET,SOCK_DGRAM,0))-1){perror(socket);exit(EXIT_FAILURE);}else{printf(create socket.\n\r);}bzero(s_addr,sizeof(s_addr));s_addr.sin_addr.s_addrINADDR_ANY;s_addr.sin_familyAF_INET;s_addr.sin_porthtons(PORT);if (bind(sock,(struct sockaddr *)s_addr,sizeof(s_addr))){perror(bind err);exit(EXIT_FAILURE);}elseprintf(bind address to socket.\n\t);addr_lensizeof(c_addr);while (1){lenrecvfrom(sock,buff,sizeof(buff)-1,0,(struct sockaddr *) c_addr,addr_len);if (len0){perror(recvfrom);exit(EXIT_FAILURE);}buff[len]\0;printf(recive come from %s:%d message:%s\n\r,inet_ntoa(c_addr.sin_addr),ntohs(c_addr.sin_port),buff);return 0;}
}send.c#include ../config.hint main(int argc,char **argv)
{struct sockaddr_in s_addr;int sock;int addr_len;int len;char buff[128];int yes;if ((socksocket(AF_INET,SOCK_DGRAM,0))-1){perror(socket);exit(EXIT_FAILURE);}elseprintf(create socket.\n\r);//开启广播yes1;setsockopt(sock,SOL_SOCKET,SO_BROADCAST,yes,sizeof(yes));s_addr.sin_familyAF_INET;s_addr.sin_porthtons(PORT);if (argv[1])s_addr.sin_addr.s_addrinet_addr(argv[1]); //广播地址:xxx.xxx.xxx.255/24else{printf(input server ip\n);exit(0);}addr_lensizeof(s_addr);strcpy(buff,hello message);lensendto(sock,buff,strlen(buff),0,(struct sockaddr *) s_addr,addr_len);if (len0){printf(\n\rsend error. \n\r);exit(EXIT_FAILURE);}printf(send success\n\r);return 0;
}./send 192.168.146.255create socket.send success抓包
UDP组播数据包
视频会议项目 1.能够在组播组中进行传播并且路由器可以进行组播数据转发 2.组播(多播)使用D类地址首位前4位1110,认为是多播地址其它28位是多播的组编号 3.224.0.0.0~239.255.255.255范围 224.0.0.0~224.0.0.255不需要路由控制 4.所有主机和终端机必须属于224.0.0.1的组 5.所有路由器必须属于224.0.0.2的组 IGMP等协议支持 struct hostent 记录主机的信息包括主机名、别名、地址类型、地址长度和地址列表 struct hostent
{char *h_name; //主机名即域名char **h_aliases; //主机所有别名构成的字符串数组同一IP可绑定多个域名int h_addrtype; //主机IP地址的类型IPv4,IPv6int h_length; //主机IP地址长度IPv4地址为4IPv6地址为16char **h_addr_list; //主机ip地址以网络字节序存储
}gethostbyname() gethostbyname函数可以利用字符串格式的域名或字符串点分十进制ip,获得IP地址并且将地址信息装入 hostent 域名结构体 #include netdb.h
struct hostent * gethostbyname(const char * hostname);返回值 成功返回hostent结构体地址 失败返回NULL指针 gethostbyaddr() 使用IP地址获取域名 #include netdb.h
struct hostent * gethostbyaddr(const char * addr,socklen_t len,int family);参数 addr:含有IP地址信息的in_addr结构体指针 len:向第一个参数传递的地址信息的字节数。ipv4为4ipv6为16 family:传递地址族信息ipv4为AF_INET,ipv6为AF_INET6 返回值 成功返回hostent结构体地址 失败返回NULL指针 struct ip_mreq
struct ip_mreq
{struct in_addr imr_multiaddr; //多播组的IP地址struct in_addr imr_interface; //加入的客户端主机IP地址
}group_brodcast_recv.c#include stdio.h
#include stdlib.h
#include string.h
#include sys/socket.h
#include sys/types.h
#include unistd.h
#include errno.h
#include netinet/in.h
#include netdb.h
#include arpa/inet.hconst int MAX_LINE 2048;
const int PORT 8888;
const int BACKLOG 10;
const int LISTENQ 6666;
const int MAX_CONNECT 20;#define BUFLEN 255int main(int argc, char **argv)
{struct sockaddr_in peeraddr;struct in_addr ia;int sockfd;char recmsg[BUFLEN 1];unsigned int socklen, n;struct hostent *group;struct ip_mreq mreq;sockfd socket(AF_INET, SOCK_DGRAM, 0);if (sockfd 0){printf(socket creating err in udptalk\n);exit(EXIT_FAILURE);}bzero(mreq, sizeof(struct ip_mreq));if (argv[1]){ //传入命令行参数1(主机域名或点分十进制字符串IP)组播地址if ((group gethostbyname(argv[1])) (struct hostent *)0)// if((groupgethostbyaddr(argv[1],sizeof(argv[1]),AF_INET))(struct hostent *)0){perror(gethostbyname);exit(EXIT_FAILURE);}}else{printf(you should give me a group address,224.0.0.0-239.255.255.255\n);exit(EXIT_FAILURE);}//组播地址写入组播组bcopy((void *)group-h_addr, (void *)ia, group-h_length);bcopy(ia, mreq.imr_multiaddr.s_addr, sizeof(struct in_addr));//命令行参数2当前IP地址写入组播组客户端IP地址列表中if (argv[2]){if (inet_pton(AF_INET, argv[2], mreq.imr_interface.s_addr) 0){printf(Wrong dest IP address!\n);exit(EXIT_FAILURE);}}//设置组播if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, mreq, sizeof(struct ip_mreq)) -1){perror(setsockopt);exit(EXIT_FAILURE);}//绑定组播地址和端口接收组播信息socklen sizeof(struct sockaddr_in);bzero(peeraddr, socklen);peeraddr.sin_family AF_INET;peeraddr.sin_port htons(PORT);if (argv[1]){if (inet_pton(AF_INET, argv[1], peeraddr.sin_addr) 0){printf(Wrong dest IP address!\n);exit(EXIT_FAILURE);}}else{printf(you should give me a group address,224.0.0.0-239.255.255.255\n);exit(EXIT_FAILURE);}if (bind(sockfd, (struct sockaddr *)peeraddr, sizeof(struct sockaddr_in)) -1){printf(Bind error\n);exit(EXIT_FAILURE);}for (;;){bzero(recmsg, BUFLEN 1);n recvfrom(sockfd, recmsg, BUFLEN, 0, (struct sockaddr *)peeraddr, socklen);if (n 0){printf(recvfrom err in udptalk\n);exit(EXIT_FAILURE);}else{recmsg[n]0;printf(perr:%s,recmsg);}}
}group_brodcast_send.c#include stdio.h
#include stdlib.h
#include string.h
#include sys/socket.h
#include sys/types.h
#include unistd.h
#include errno.h
#include netinet/in.h
#include netdb.h
#include arpa/inet.hconst int MAX_LINE 2048;
const int PORT 8888;
const int BACKLOG 10;
const int LISTENQ 6666;
const int MAX_CONNECT 20;#define BUFLEN 255int main(int argc, char **argv)
{struct sockaddr_in peeraddr,myaddr;int sockfd;char recmsg[BUFLEN 1];unsigned int socklen;sockfd socket(AF_INET, SOCK_DGRAM, 0);if (sockfd 0){printf(socket creating err in udptalk\n);exit(EXIT_FAILURE);}//组播socklensizeof(struct sockaddr_in);bzero(peeraddr,socklen);peeraddr.sin_familyAF_INET;peeraddr.sin_porthtons(PORT);//组播客户端绑定的端口//命令行参数1为组播地址if (argv[1]){if (inet_pton(AF_INET, argv[1], peeraddr.sin_addr) 0){printf(Wrong dest IP address!\n);exit(EXIT_FAILURE);}}else{printf(you should give me a group address,224.0.0.0-239.255.255.255\n);exit(EXIT_FAILURE);}//绑定本机IP和端口bzero(myaddr,socklen);myaddr.sin_familyAF_INET;myaddr.sin_porthtons(23456);//命令行参数2为本机IPif (argv[2]){if (inet_pton(AF_INET,argv[2],myaddr.sin_addr)0){printf(self ip address error\n);exit(EXIT_FAILURE);}}elsemyaddr.sin_addr.s_addrINADDR_ANY;if (bind(sockfd,(struct sockaddr *)myaddr,sizeof(struct sockaddr_in))-1){printf(Bind error\n);exit(EXIT_FAILURE);}for(;;){bzero(recmsg,BUFLEN1);printf(input message to send:);if (fgets(recmsg,BUFLEN,stdin)(char *)EOF){exit(EXIT_FAILURE);}//发送组播消息if (sendto(sockfd,recmsg,strlen(recmsg),0,(struct sockaddr *)peeraddr,sizeof(struct sockaddr_in))0){printf(sendto error\n);exit(EXIT_FAILURE);}printf(send message:%s,recmsg);}
}接收端 发送端 抓包