- 每次复制代码时,如果代码里有 // 这样的注释就容易让格式乱掉 >>>set paste后再粘贴即可
第一节 网络信息检索
1.1 gethostbyname函数
struct hostent *gethostbyname(const char *hostname); |
---|
功能:获取主机host的IP地址通过域名name (由于服务器的域名是不会变的,服务器的IP是变化的,通过该方式可以获取IP地址) |
参数 : 域名 |
返回值: hostent 结构体 struct hostent{ char *h_name;//official name官方域名 char **h_aliases; //alias list别名 int h_addrtype;//host address type,IPv4还是IPv6 int h_length;//address lenght保存IP地址长度 char **h_addr_list; //address list,IP地址(网络地址,如果用户需要查看,需要用inet_ntop转成点分十进制的地址) } |
使用gethostbuname查看www.baidu.com的IP地址,并用点分十进制显示出来 1 =============================================================== 2 * Copyright (C) 2020 All rights reserved. 3 * 4 * 文件名称:text1.c 5 * 创 建 者:liujing 6 * 创建日期:2020年07月28日 7 * 描 述: 8 * 通过代码获取www.baidu.com的IP地址 9 * 更新日志: 10 * 11 ================================================================*/ 12 #include <stdio.h> 13 #include <string.h> 14 #include <stdlib.h> 15 #include <strings.h> 16 #include <netdb.h> 17 #include <sys/socket.h> 18 #include <netinet/in.h> 19 #include <arpa/inet.h> 20 void main() 21 { 22 //定义结构体指针来接收host的IP信息 23 struct hostent*Hostent; 24 25 Hostent = gethostbyname("www.baidu.com"); 26 27 printf("\n官方域名:%s\n",Hostent->h_name); 28 printf("\n别名:%s\n",*Hostent->h_aliases); 29 printf("\n类型:%d\n",Hostent->h_addrtype); 30 printf("\nIP长度:%d\n",Hostent->h_length); 31 32 char str[32]; 33 //将网络地址-->点分十进制地址存储在str 34 inet_ntop(Hostent->h_addrtype,*Hostent->h_addr_list,str,32); 35 printf("\nIP地址:%s\n",str); 36 37 } ================================================================* 运行结果与IP验证: farsight@ubuntu:~/Desktop$ ./a.out 官方域名:www.a.shifen.com 别名:www.baidu.com 类型:2 IP长度:4 IP地址:61.135.169.121 farsight@ubuntu:~/Desktop$ ping www.baidu.com PING www.a.shifen.com (61.135.169.125) 56(84) bytes of data. 64 bytes from 61.135.169.125: icmp_req=1 ttl=54 time=40.8 ms 64 bytes from 61.135.169.125: icmp_req=2 ttl=54 time=42.4 ms 64 bytes from 61.135.169.125: icmp_req=3 ttl=54 time=49.9 ms ==>成功 ================================================================*
第二节 网络属性设置(了解)
2.1 setsockopt
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen); |
---|
参数1:sockfd是被修改的socket描述符 |
参数2 :level:需要修改哪一类套接字 SOL_SOCKET: 基本套接口 IPPROTO_IP: IPv4套接口 IPPROTO_IPV6: IPv6套接口 IPPROTO_TCP: TCP套接口 |
参数3:你要修改的那个属性 |
参数4:optval是重新写入的属性的值 |
参数5:optlen代表重新写入的属性的值的大小 |
第三节 超时检查
- 避免进程在没有数据时无限制地阻塞
3.1 使用setsockopt实现网络超时检测
- 设置一次,永久有效。对所有和网络相关的阻塞函数有效
- 当使用accept/recvfrom这类阻塞函数时,会自动设置最大阻塞休眠时间为我们setsockopt设置的超时时间
struct timeval time_out; time_out.tv_sec=5; time_out.tv_usec=0; //SO_RCVTIMEO 设置接收超时时间 if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &time_out, sizeof(time_out)) < 0) { perror("fail to setsockopt"); } ==> TCP套接字中的recv/accept UDP套接字中的recvfrom
3.2 使用select函数实现网络超时检测
- int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);可以设置最大select时间,来判断socket网络是否超时
3.3 使用alarm闹钟实现网络超时检测
- 当闹钟响时,会触发SIGALRM信号,执行信号处理函数,当信号处理函数执行完毕,会接着刚才的代码继续执行
第四节 广播 //UDP编程
-
同时发给局域网中的所有主机,称为广播;
-
只有UDP协议套接字才能广播
广播编程注意 { 接收端 1:UDP套接字 2:修改UDP套接字的属性 3:bind //接收端地址=广播地址;广播地址与本机IP都可以bind 4:recvfrom接收 发送端: 1:UDP套接字 2:修改UDP套接字的属性 4:sendto发送 }
发送端与接收端通过广播地址进行广播通信 接收端代码: =============================================================== * Copyright (C) 2020 All rights reserved. * * 文件名称:ser.c * 创 建 者:liujing * 创建日期:2020年07月28日 * 描 述: * 通过代码获取www.baidu.com的IP地址 * 更新日志: * ================================================================*/ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <strings.h> #include <netdb.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> void main() { printf("\nsocket success\n"); //创建UDP的套接字 int socket_fd; socket_fd =socket(AF_INET,SOCK_DGRAM,0); if(socket_fd == -1) { perror("\nsocket error\n"); } else { printf("\nsocket success\n"); } //设置UDP的套结字为广播类型 //基本套结字+允许套结字传送广播信息+(1=允许) int value = 1; //允许 if(-1 == setsockopt(socket_fd,SOL_SOCKET,SO_BROADCAST,(const void *)&value,(socklen_t)sizeof(value))) { perror("\nsetsockopt error\n"); } else { printf("\nsetsockopt success\n"); } //bind服务器的网络地址 struct sockaddr_in addrto; addrto.sin_family=AF_INET; //由于服务器处于192.168.43网段,服务器作为UDP的接受方,服务器的IP绑定为广播地址 //接受方的地址=广播地址 inet_pton(AF_INET,"192.168.43.255",&addrto.sin_addr.s_addr); addrto.sin_port=5001; int nlen=sizeof(addrto); if(-1 == bind(socket_fd,(const struct sockaddr *)&addrto,nlen)) { perror("bind error"); } else { printf("bind success"); } //UDP发送 while(1) { char str[32] = "hello word"; //接收 if(recvfrom(socket_fd,str,32,0,(struct sockaddr *)&addrto, &nlen) < 0) { perror("\nsendto error\n"); } else { printf("\nget %s\n",str); } sleep(2); } } 发送端代码: =============================================================== * Copyright (C) 2020 All rights reserved. * * 文件名称:cli.c * 创 建 者:liujing * 创建日期:2020年07月28日 * 描 述: * 通过代码获取www.baidu.com的IP地址 * 更新日志: * ================================================================*/ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <strings.h> #include <netdb.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> void main() { printf("\nsocket success\n"); //创建UDP的套接字 int socket_fd; socket_fd =socket(AF_INET,SOCK_DGRAM,0); if(socket_fd == -1) { perror("\nsocket error\n"); } else { printf("\nsocket success\n"); } //设置UDP的套结字为广播类型 //基本套结字+允许套结字传送广播信息+(1=允许) int value = 1; //允许 if(-1 == setsockopt(socket_fd,SOL_SOCKET,SO_BROADCAST,(const void *)&value,(socklen_t)sizeof(value))) { perror("\nsetsockopt error\n"); } else { printf("\nsetsockopt success\n"); } //bind服务器的网络地址 struct sockaddr_in addrto; addrto.sin_family=AF_INET; inet_pton(AF_INET,"192.168.43.255",&addrto.sin_addr.s_addr); addrto.sin_port=5001; int nlen=sizeof(addrto); //UDP发送 while(1) { char str[32] = "hello word"; //发送 if(sendto(socket_fd,str,32,0,(struct sockaddr *)&addrto, nlen) < 0) { perror("\nsendto error\n"); } else { printf("\nsend %s\n",str); } sleep(2); } } ================================================================ 发送端运行如下 farsight@ubuntu:~/Desktop$ ./cli socket success socket success setsockopt success send hello word send hello word send hello word send hello word send hello word send hello word ================================================================ 接收端运行如下: farsight@ubuntu:~/Desktop$ ./ser socket success socket success setsockopt success bind success get hello word get hello word get hello word get hello word get hello word get hello word ================================================================
第五节 组播 //UDP
- 广播的时候,接收端必须调用bind函数指定接收端的端口号,显示的指定自己用的端口号
- 组播,必须使用UDP协议。有专门的组播地址
- [ ]