[疑难] 请教 异步 gethostbyname
hurd
2009-05-03
小弟最近在写个windows控制台程序, 需要用到异步gethostbyname。
windows下有个WSAAsyncGetHostByName,但是必须用窗口线程来接受结果。 请教有什么办法能不用窗口,又不必创建多个线程的解决办法。 |
|
zhangyafei_kimi
2009-05-03
boost好像可以,我记得例子里面有。
|
|
zhangyafei_kimi
2009-05-03
不好意思,没看清楚这里是D论坛
|
|
qiezi
2009-05-04
可以自己解析dns协议。。
|
|
hurd
2009-05-05
写个一个阻塞的,调用receiveFrom一直返回-1,哪位有空给看看程序。
import tango.sys.win32.UserGdi, tango.io.Stdout, tango.core.Array, tango.net.SocketConduit, tango.net.InternetAddress, tango.net.Socket; alias tango.net.Socket.htons htons; void main(){ char[1024 * 2] buf2; DNS_HEADER* dns = cast(DNS_HEADER*) &buf2[0]; dns.id = htons(1); dns.rd = htons(1); dns.q_count = htons(1); int offset = DNS_HEADER.sizeof + ChangetoDnsNameFormat("www.baidu.com", buf2[ DNS_HEADER.sizeof .. $ ]) ; QUESTION* dnsq = cast(QUESTION*) &buf2[ offset ]; dnsq.qtype = htons(12); //reverse DNS : adresse -> nom dnsq.qclass = htons(1); offset += QUESTION.sizeof; Stdout.formatln("{}", buf2[0..offset+0]); auto soc = new Socket(AddressFamily.INET, SocketType.DGRAM, ProtocolType.UDP); auto addr = new InternetAddress("192.168.0.1", 55); soc.blocking(true); //soc.setLingerPeriod(1); if( soc.connect(addr)){ soc.sendTo(buf2[0..offset], SocketFlags.NONE , addr); char[] buf = new char[1024]; int i = soc.receiveFrom(buf, SocketFlags.NONE , addr); if( i > 0 && i< buf.length){ Stdout.formatln("{}", buf[0..i]); }else{ Stdout.formatln("receiveFrom return :{} ", i); } soc.detach(); } } /* DNS_HEADER QTYPE:查询类型,两个八位组。表示: A 1 主机地址 NS 2 授权管理域名服务器 CNAME 5 主机规范名字 SOA 6 授权开始 PTR 12 域名指针 MX 15 邮件服务器 QCLASS:IN或CH */ struct DNS_HEADER { WORD Xid ; //A value that specifies the unique DNS message identifier. align(1): BYTE RecursionDesired ; //A value that specifies whether recursive name query should be used by the DNS name server. // 0x00 Do not use recursive name query. // 0x01 Use recursive name query. BYTE Truncation ; //A value that specifies whether the DNS message has been truncated. //0x00 The message is not truncated. //0x01 The message is truncated. BYTE Authoritative ; //A value that specifies whether the DNS server from which the DNS message is being sent is authoritative for the domain name's zone. //0x00 The DNS server is not authoritative in the zone. //0x01 The DNS server is authoritative in the zone. align(4): BYTE Opcode ; //A value that specifies the operation code to be taken on the DNS message as defined in section 4.1.1 of RFC 1035 as the OPCODE field. align(1): BYTE IsResponse ; //A value that specifies whether the DNS message is a query or a response message. //0x00 The DNS message is a query. //0x01 The DNS message is a response. align(4): BYTE ResponseCode = 4 ; //The DNS Response Code of the message. align(1): BYTE CheckingDisabled ; //Windows 7 or later: A value that specifies whether checking is supported by the DNS resolver. //0x00 Checking is enabled on the DNS resolver. //0x01 Checking is disabled on the DNS resolver. BYTE AuthenticatedData ; //Windows 7 or later: A value that specifies whether the DNS data following the DNS_HEADER is authenticated by the DNS server. //0x00 The DNS data is not authenticated. //0x01 The DNS data is authenticated. BYTE Reserved ; //Reserved. Do not use. BYTE RecursionAvailable ; //A value that specifies whether recursive name query is supported by the DNS name server. //0x00 Recursive name query is not supported. //0x01 Recursive name query is supported. align(4): WORD QuestionCount ; //The number of queries contained in the question section of the DNS message. WORD AnswerCount ; //The number of resource records (RRs) contained in the answer section of the DNS message. WORD NameServerCount ; //The number of DNS name server RRs contained in the authority section of the DNS message. This value is the number of DNS name servers the message has traversed in its search for resolution. WORD AdditionalCount ; //Reserved. Do not use. alias Xid id; alias CheckingDisabled rd; alias QuestionCount q_count; } //set up the header //dns->id = (unsigned short)htons(GetCurrentProcessId()); //dns->qr = 0; //This is a query //dns->opcode = 0; //This is a standard query //dns->aa = 0; //Not Authoritative //dns->tc = 0; //This message is not truncated //dns->rd = 1; //Recursion Desired //dns->ra = 0; //Recursion not available! hey we dont have it (lol) //dns->z = 0; //dns->ad = 0; //dns->cd = 0; //dns->rcode = 0; //dns->q_count = htons(1); //we have only 1 question //dns->ans_count = 0; //dns->auth_count = 0; //dns->add_count = 0; struct QUESTION { WORD qtype; WORD qclass; } int ChangetoDnsNameFormat(char[] host, char[] buf){ assert(buf.length > host.length); char* ptr = &buf[0]; int len; while(true){ int i = find(host, '.'); if( i == host.length ){ buf[0] = i; buf[1..i+1] = host; len = &buf[i+2] - ptr; ptr[len-1] = 0; break; } buf[0] = i; buf[1..i+1] = host[0..i]; host = host[i+1..$]; buf = buf[i+1..$]; } return len; } |