|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
归根到底,Java跨平台可以,但是要重新编写代码,否则还分什么J2EE/J2SE/J2ME呢!本章接上章Socket编程(二)
10、收集参数的设置和猎取
取得主机名存到hostname中
intgethostname(char*hostname,size_tsize);
获得当地的SOCKET信息
intgetsockname(intsockfd,structsockaddr*addr,int*addrlen);
获得对方主机的SOCKET信息
intgetpeername(intsockfd,structsockaddr*addr,int*addrlen);
取得DNS信息:
structhostent*gethostbyname(constchar*name);
structhostent*gethostbyaddr(constchar*addr,intlen,inttype);
前往了一个指向structhostent的指针,structhostent界说以下:
structhostent{
char*h_name;/*主机域名*/
char**h_aliases;/*别号*/
inth_addrtype;/*地点范例*/
inth_length;/*IP地点长度*/
char**h_addr_list;/*IP地点链*/
};
#defineh_addrh_addr_list[0]
gethostbyname经由过程设置h_errno代表堕落号,对应的毛病函数有hstrerror()和herror(),分离对应于strerror()和perror()这两个一般的毛病函数。取得或改动socket属性
intgetsockopt(intsockfd,intlevel,intname,char*value,int*optlen);
intsetsockopt(intsockfd,intlevel,intname,char*value,int*optlen);
level:(级别):指定选项代码的范例。
SOL_SOCKET:基础套接口
IPPROTO_IP:IPv4套接口
IPPROTO_IPV6:IPv6套接口
IPPROTO_TCP:TCP套接口
level通常是常数SOL_SOCKET
name选项称号
value选项值:是一个指向变量的指针,变量能够是整形,套接口布局,其他布局范例:linger{},timeval{}
optlenoptval的巨细经常使用选项的有:
[SOL_SOCKET
]SO_BROADCAST同意发送播送数据int
合用於UDPsocket。其意义是同意UDPsocket「播送(broadcast)讯息到网路上。
SO_DEBUG同意调试int
SO_DONTROUTE不查找路由int
SO_ERROR取得套接字毛病int
SO_KEEPALIVE坚持毗连int
检测对方主机是不是溃散,制止(服务器)永久堵塞于TCP毗连的输出。设置该选项后,假如2小时内涵此套接口的任一偏向都没无数据互换,TCP就主动给对方发一个坚持存活探测分节(keepaliveprobe)。这是一个对方必需呼应的TCP分节.它会招致以下三种情形:对方吸收统统一般:以希冀的ACK呼应。2小时后,TCP将收回另外一个探测分节。对方已溃散且已从头启动:以RST呼应。套接口的待处置毛病被置为ECONNRESET,套接口自己则被封闭。对方无任何呼应:源自berkeley的TCP发送别的8个探测分节,相隔75秒一个,试图失掉一个呼应。在收回第一个探测分节11分钟15秒后若仍无呼应就保持。套接口的待处置错误被置为ETIMEOUT,套接口自己则被封闭。如ICMP毛病是“hostunreachable(主机不可达)”,申明对方主机并没有溃散,可是不成达,这类情形下待处置毛病被置为EHOSTUNREACH。
SO_DONTLINGER若为真,则SO_LINGER选项被克制。
SO_LINGER提早封闭毗连
structlinger下面这两个选项影响close举动选项距离封闭体例守候封闭与否
SO_DONTLINGER不体贴文雅否
SO_LINGER零强迫否
SO_LINGER非零文雅是
若设置了SO_LINGER(亦即linger布局中的l_onoff域设为非零,拜见2.4,4.1.7和4.1.21
各节),并设置了零超工夫隔,则closesocket()不被堵塞当即实行,不管是不是有列队数据未发送或未被确认。这类封闭体例称为“强迫”或“生效”封闭,由于套接口的虚电路当即被复位,且丧失了未发送的数据。在远真个recv()挪用将以WSAECONNRESET堕落。
若设置了SO_LINGER并断定了非零的超工夫隔,则closesocket()挪用堵塞历程,直到所剩数据发送终了或超时。这类封闭称为“文雅的”封闭。请注重假如套接口置为非堵塞且SO_LINGER设为非零超时,则closesocket()挪用将以WSAEWOULDBLOCK毛病前往。
若在一个流类套接口上设置了SO_DONTLINGER(也就是说将linger布局的l_onoff域设为零;拜见2.4,4.1.7,4.1.21节),则closesocket()挪用当即前往。可是,假如大概,列队的数据将在套接口封闭前发送。
SO_OOBINLINE带外数据放进一般数据流,在一般数据流中吸收带外数据int
SO_RCVBUF吸收缓冲区巨细int
设置吸收缓冲区的保存巨细,与SO_MAX_MSG_SIZE或TCP滑动窗口有关,假如一样平常发送的包很年夜很频仍,那末利用这个选项
SO_SNDBUF发送缓冲区巨细int
设置发送缓冲区的保存巨细
与SO_MAX_MSG_SIZE或TCP滑动窗口有关,假如一样平常发送的包很年夜很频仍,那末利用这个选项
每一个套接口都有一个发送缓冲区和一个吸收缓冲区。吸收缓冲区被TCP和UDP用来将吸收到
的数据一向保留到由使用历程来读。
TCP:TCP公告另外一真个窗口巨细。TCP套接口吸收缓冲区不成能溢出,由于对方不同意收回凌驾所公告窗口巨细的数据。这就是TCP的流量把持,假如对方忽视窗口巨细而收回了凌驾宙口巨细的数据,则接收方TCP将抛弃它。
UDP:当吸收到的数据报装不进套接口吸收缓冲区时,此数据报就被抛弃。UDP是没有流量把持的;快的发送者能够很简单地就吞没慢的吸收者,招致吸收方的UDP抛弃数据报。SO_RCVLOWAT吸收缓冲区上限int
SO_SNDLOWAT发送缓冲区上限int
每一个套接口都有一个吸收高潮限制和一个发送高潮限制。它们是函数selectt利用的,吸收高潮限制是让select前往“可读”而在套接口吸收缓冲区中必需有的数据总量。——关于一个TCP或UDP套接口,此值缺省为1。发送高潮限制是让select前往“可写”而在套接口发送缓冲区中必需有的可用空间。关于TCP套接口,此值常缺省为2048。关于UDP利用高潮限制,因为其发送缓冲区中可用空间的字节数是从稳定化的,只需UDP套接口发送缓冲区巨细年夜于套接口的高潮限制,如许的UDP套接口就老是可写的。UDP没有发送缓冲区,只要发送缓冲区的巨细。
SO_RCVTIMEO吸收超时structtimeval
SO_SNDTIMEO发送超时structtimeval
SO_BROADCAST:取得或设置socket情况,使之能够播送发送数据报。(只能用于UDP体例)。
SO_REUSEADDR:设置该socket绑定的端口能够被重用。
注重:在Linux体系中,假如一个socket绑定了某个端口,该socket一般封闭或程序加入后,
在一段工夫内该端口仍然坚持被绑定的形态,其他程序(大概从头启动的原程序)没法绑定该端口。能够经由过程挪用以下语句制止该成绩:
opt=1;
len=sizeof(opt);
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,&len);SO_EXCLUSIVEADDRUSE
独有形式利用端口,就是不充许和别的程序利用SO_REUSEADDR共享的利用某一端口。
在断定多重绑定利用谁的时分,依据一条准绳是谁的指定最明白则将包递交给谁,并且没有权限之分,也就是说初级权限的用户是能够重绑定在初级权限如服务启动的端口上的,这长短常严重的一个平安隐患,假如不想让本人程序被监听,那末利用这个选取得或改动socket的I/O属性:
intioctl(intsockfd,longcmd,unsignedlong*argp);
cmd属性范例,argp属性的参数。
经常使用的有:
FIONREAD,前往socket缓冲区中未读数据的字节数
FIONBIO,argp为零时为堵塞形式,非零时为非堵塞形式
SIOCATMARK,判别是不是有未读的带外数据(仅用于TCP协定),前往true或false
intfcntl(intfd,intcmd,longarg);
F_SETFL,arp为O_NONBLOCK时进进非堵塞形式,为0时进进堵塞形式。
F_GETFL,取得属性。挪用ioctl猎取体系收集接口的信息:
structifconf{
intifc_len;//为ifc_buf缓冲区的巨细
union{
caddr_tifcu_buf;//被界说为ifc_buf,用户界说传送到内核
structifreq*ifcu_req;//被界说为ifc_req,内核前往到用户
}ifc_ifcu;
};
sturctifreq{
charifr_name[IFNAMSIZ];//网卡名字,如hme0,IFNAMSIZ=16
union{
structsockaddrifru_addr;//界说为ifr_addr,主IP地点;
structsockaddrifru_dstaddr;//界说为ifr_dstaddr;
structsockaddrifru_broadaddr;//界说为ifr_broadaddr;
shortifru_flags;//界说为ifr_flags,参考<net/if.h>
intifru_flags;//界说为ifr_flags
intifru_metric;//界说为ifr_metric
caddr_tifru_data;//界说为ifr_data
}ifr_ifru;
}
例子:(在SOLARIS情况下经由过程)
输出IP地点,前往MAC地点:
#include<sys/types.h>
#include<sys/sockio.h>
#include<sys/param.h>
#include<errno.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<netdb.h>
#include<sys/types.h>
#include<unistd.h>
#include<stropts.h>
#include<net/if.h>
#include<stdio.h>
#include<sys/ioctl.h>
#include<net/if_arp.h>intmain(intargc,char**argv)
{
intsockfd;
char*ptr;
structarpreqarp;
structsockaddr_in*arptr;sockfd=socket(AF_INET,SOCK_STREAM,0);//createanytypeofsocket
arptr=(structsockaddr_in*)&arp.arp_pa;
bzero(arptr,sizeof(structsockaddr_in));
arptr->sin_family=AF_INET;
arptr->sin_addr.s_addr=inet_addr(argv[1]);
ioctl(sockfd,SIOCGARP,&arp);
printf("addr=%s,arpmac=%x%x%x%x%x%x%x%x
",
inet_ntoa(arptr->sin_addr),arp.arp_ha.sa_data[0],arp.arp_ha.sa_da
ta[1],arp.arp_ha.sa_data[2],arp.arp_ha.sa_data[3],arp.arp_ha.sa_data[4],
arp.arp_ha.sa_data[5],arp.arp_ha.sa_data[6],arp.arp_ha
.sa_data[7],arp.arp_ha.sa_data[8]);
ptr=arp.arp_ha.sa_data;
printf("mac=%x:%x:%x:%x:%x:%x
",*(ptr)&0xff,*(ptr+1)&0xff,
*(ptr+2)&0xff,*(ptr+3)&0xff,*(ptr+4)&0xff,*(ptr+5)&0xff);
}
依据网卡名字输入MAC地点:
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/ioctl.h>
#include<netinet/in.h>
#include<net/if.h>
#include<net/if_arp.h>
#include<arpa/inet.h>
#include<errno.h>
#include<sys/sockio.h>#defineETH_NAME"eri0"intmain()
{
intsock;
structsockaddr_insin;
structifreqifr;sock=socket(AF_INET,SOCK_DGRAM,0);
if(sock-1)
perror("socket");
return-1;
}strncpy(ifr.ifr_name,ETH_NAME,IFNAMSIZ);
ifr.ifr_name[IFNAMSIZ-1]=0;if(ioctl(sock,SIOCGIFADDR,&ifr)<0)
{
perror("ioctl");
return-1;
}memcpy(&sin,&ifr.ifr_addr,sizeof(sin));
fprintf(stdout,"hme0:%s
",inet_ntoa(sin.sin_addr));return0;
}
输入以后体系一切UP形态的收集接口的IP地点,MAC地点等信息
#include<sys/types.h>
#include<sys/sockio.h>
#include<sys/param.h>
#include<errno.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<netdb.h>
#include<sys/types.h>
#include<unistd.h>
#include<stropts.h>
#include<net/if.h>
#include<stdio.h>
#include<sys/ioctl.h>
#include<net/if_arp.h>
#defineINTERFACE_NUM5
structmy_inte{
charinte_name[16];
charmac[8];
shortmac_len;
shortflags;
structsockaddrprimary_addr;
structsockaddrbroad_addr;
structsockaddrdest_addr;
structsockaddrnetmask;
structmy_inet*next;
};
voidlist(structmy_inte*ptr)
{
structsockaddr_in*addr;
printf("inteface_name=%s
",ptr->inte_name);
printf("mac=%x:%x:%x:%x:%x:%x
",*(ptr->mac)&0xff,*(ptr->mac+1)&0xff,
*(ptr->mac+2)&0xff,*(ptr->mac+3)&0xff,*(ptr->mac
+4)&0xff,*(ptr->mac+5)&0xff);
printf("flags=%d",ptr->flags);
if(ptr->flags&IFF_UP)printf("up");
if(ptr->flags&IFF_BROADCAST)printf("broadcast")
if(ptr->flags&IFF_MULTICAST)printf("multicast");
if(ptr->flags&IFF_LOOPBACK)printf("loopback");
if(ptr->flags&IFF_POINTOPOINT)printf("pointtopoint");
printf("
");
addr=(structsockaddr_in*)&ptr->primary_addr;
printf("primary_addr=%s
",inet_ntoa(addr->sin_addr));
addr=(structsockaddr_in*)&ptr->netmask;
printf("netmask=%s
",inet_ntoa(addr->sin_addr));
addr=(structsockaddr_in*)&ptr->broad_addr;
printf("broad_addr=%s
",inet_ntoa(addr->sin_addr));
addr=(structsockaddr_in*)&ptr->dest_addr;
printf("dest_addr=%s
",inet_ntoa(addr->sin_addr));
}
intmain(intargc,char**argv)
{
intsockfd,len,lastlen,flags;
char*buf,*ptr;
structifconfinterfaces;
structifreq*inteptr,intecopy;
structmy_inte*head,*tail,*my_inte_ptr,*tmpptr;
structarpreqarp;
structsockaddr_in*arptr;
sockfd=socket(AF_INET,SOCK_STREAM,0);//createanytypeofsocket
lastlen=0;
len=INTERFACE_NUM*sizeof(structifreq);
for(;;){
buf=(char*)malloc(len);
interfaces.ifc_len=len;
interfaces.ifc_buf=buf;
if(ioctl(sockfd,SIOCGIFCONF,&interfaces)<0){
if(errno!=EINVAL||lastlen!=0){//ifreturnEINVALandnot
returnsucceed
perror("ioctlerror");
return;
}
}
else
{
if(interfaces.ifc_len==lastlen)
break;
lastlen=interfaces.ifc_len;
}
len+=INTERFACE_NUM*sizeof(structifreq);
free(buf);
}
head=tail=NULL;
for(ptr=buf;ptr<buf+interfaces.ifc_len;){
inteptr=(structifreq*)ptr;
ptr+=sizeof(inteptr->ifr_name)+sizeof(structsockaddr);//ptrpioint
tonextifreqstruct
intecopy=*inteptr;
ioctl(sockfd,SIOCGIFFLAGS,&intecopy);
flags=intecopy.ifr_flags;
if(flags&IFF_UP==0)//ignoredownnetworkcard
continue;
my_inte_ptr=(structmy_inte_ptr*)calloc(1,sizeof(structmy_inte));
//createaself-definedstruct
my_inte_ptr->next=NULL;
my_inte_ptr->flags=flags;
bzero(&(my_inte_ptr->inte_name),16);
strncpy(my_inte_ptr->inte_name,inteptr->ifr_name,16-1);
memcpy(&my_inte_ptr->primary_addr,&(*inteptr).ifr_addr,sizeof(struct
sockaddr));//IPaddr
arptr=(structsockaddr_in*)&arp.arp_pa;
bzero(arptr,sizeof(structsockaddr_in));
arptr->sin_family=AF_INET;
arptr->sin_addr=((structsockaddr_in
*)(&my_inte_ptr->primary_addr))->sin_addr;
ioctl(sockfd,SIOCGARP,&arp);
printf("addr=%s,arpmac=%x%x%x%x%x%x%x%x
",
inet_ntoa(arptr->sin_addr),arp.arp_ha.sa_data[0],arp.arp_ha.sa_da
ta[1],arp.arp_ha.sa_data[2],arp.arp_ha.sa_data[3],arp.arp_ha.sa_data[4],
arp.arp_ha.sa_data[5],arp.arp_ha.sa_data[6],arp.arp_ha
.sa_data[7],arp.arp_ha.sa_data[8]);
memcpy(my_inte_ptr->mac,arp.arp_ha.sa_data,8);//MAC
ioctl(sockfd,SIOCGIFNETMASK,&intecopy);
my_inte_ptr->netmask=intecopy.ifr_addr;
if(flags&IFF_BROADCAST){
ioctl(sockfd,SIOCGIFBRDADDR,&intecopy);
my_inte_ptr->broad_addr=intecopy.ifr_broadaddr;
}
if(flags&IFF_POINTOPOINT){
ioctl(sockfd,SIOCGIFDSTADDR,&intecopy);
my_inte_ptr->dest_addr=intecopy.ifr_dstaddr;
}
if(head==NULL)
head=tail=my_inte_ptr;
else
tail->next=my_inte_ptr;
}
free(buf);
//listthelist
for(my_inte_ptr=head;my_inte_ptr!=NULL;){
tmpptr=my_inte_ptr;
my_inte_ptr=my_inte_ptr->next;
list(tmpptr);
free(tmpptr);
}
}
ARP高速缓存:
由ioctl保护
stuctarpreq{
structsockaddrapr_pa;//IP地点
structsockaddrarp_ha;//MAC地点
intarp_flags;
}
相干的操纵有:
1.SIGCSARP:增添或修正一个ARP高速缓冲区的条目
2.SIGCDARP:删除一个条目
3.SIGCGARP:掏出一个条目
路由套接口:
经由过程路由套接口互换的布局有3种:
1.Structrt_msghdr{
U_shortrtm_msglen;//动静长度,包含头和厥后的SOCKET地点布局
U_charrtm_version;
U_charrtm_type;//操纵范例,如RTM_GET
U_shortrtm_index;
intrtm_flags;
intrtm_addrs;//位掩码,如RTA_DST,暗示头布局后的SOCKET地点布局的范例
pid_trtm_pid;
intrtm_seq;
intrtm_errno;
intrtm_inits;
structrt_metricsrtm_rmx;
}
2.Structif_msghdr{…}
3.Structifa_msghdr{…}
以上动静布局由用户填写部分信息发往内核,前往的数据在struct…_msghdr布局以后将最多有8个SOCKET布局,为:DST、GATEWAY、NETMASK、GENMASK、IFP、IFR、AUTHOR、BRD套接字布局
本章内容来自于互联网,小编只卖力排版,因受小编手艺所限,偶然断句的中央其实不正确,但小编已全力让本章收拾的更有可读性,请体谅。因小编保留这篇文章工夫太长,已记不清来历,以是未标注来历,敬请体谅!来吧!老师们!我代表千千万万的asp.net/C#的初学者在这里呼唤着! |
|