已阅读5页,还剩17页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
综合课程设计说明书 第 22 页 共 22 页VC+实现探测远程主机是否可达1. 课程设计目的1.1 了解探测远程主机是否可达的方法;1.2 了解windows网络编程的基本步骤;1.3 了解TCP/IP协议及ICMP协议;1.4 掌握ping命令的思想;1.5 掌握Windows Socket API的使用方法。2. 课程设计要求2.1 基于Visual C+6.0编程环境实现;2.2 采用Windows Socket API相关函数实现;2.3 设计结果通过Windows界面显示;3. 设计原理3.1 ping命令的运行Ping命令使用ICMP协议,具有测试网络中某台计算机是否可达、记录路由和时间戳等功能。ICMP协议(Internet control message protocol,网际控制报文协议)是TCP IP协议族的一个子协议。该协议位于网络层,提供了传输差错报文、控制报文和询问报文的功能,允许ICMP报文在IP数据报内携带。应用程序可以直接从原始IP接口发送或接收ICMP报文。Ping命令是使用了ICMP协议众多报文中的请求报文(echo)和请求。Ping命令用来确定主机是否存在,是否可达。通过一个ping回显请求,并把它发送到感兴趣的主机,然后等待回应,根据是否收到目标的回显应答,便可以确定是否可以成功地到达该主机。但若是远程主机已经关机或没有开启监听功能,便不能到达,这时要使用超时控制,当超过一定的时间还未收到回复,便认为该主机不可到达,为了提高ping命令测试的可信度,ping命令重传四次,四次中一次都接收不到回复便认为远程主机不可到达。ICMP报文封装在IP数据报的数据部分,以IP数据报的形式在网络中传输。格式如下:IP首部(固定20B)ICMP报文ICMP报文的格式如下:类型(8b)代码(8b)校验和(16b)参数(若没有参数,则不用)内容(取决于类型和代码)其中,类型为0表示该报文是对请求回复的响应应答,类型为8表示该报文是包含回应的响应请求,此时参数一项为16位标识符和16位序号。当接收方接收到该请求报文,它就把源地址和目的地址到倒换过来,重新计算校验和,然后向发送方返回一个响应回复的报文;如果数据域中有数据的话,也会返回发送方。IP数据报的格式如下:版本(8b)报文长度(8b)服务类型(8b)总长度(8b)标识(16b)标志(3b)片偏移(13b)生存时间(8b)协议(8b)报头校验和(16b)源IP地址(32b)目标IP地址(32b)选项(如果有)数据IP选项头格式:代码(1B)长度(1B)偏移(1B)选项专用数据(37B)IP选项占40个字节,在稍后的程序将定义3 + 4 * 9 = 39个字节,还有一个字节由系统自动填充。3.2 Winsock 和原始套接字Winsock是一种标准API(应用程序编程接口),主要用于网络中的数据通信,它允许两个或者多个应用程序(或进程)在同一台机器上或通过网络相互通信。Winsock主要有两个版本,即Winsock1和Winsock2。在编译时若使用头文件WINSOCK.H时须使用WSOCK32.LIB库文件,采用了头文件WINSOCK2.H的应用程序时,须链接到WS2_32.LIB库。包含了所需要的头文件和链接环境,就可以开始编写应用程序代码了。本文用Winsock2版本,包含头文件的做法是在程序代码前加上编译预处理指令:#include 或#include winsock2.h。并且必须链接到库文件ws2_32.lib,否则将会出现编译错误!原始套接字允许访问底层传输协议的一种套接字类型。使用原始套接字操作IP数据报,可以进行路由根据,ping等。原始套接字有两种类型,一是IP头中使用预定义的协议,如ICMP;二是在IP头中使用自定义的协议。后面的程序中将用到的Windows Socket API的函数的叙述:加载Winsock库是通过WSAStartup()函数实现的,int WSAStart(版本,指向LPWSADATA结构的指针),第一个参数可以使用MAKEWORD(x,y),x是高位字节,指定所需Winsock库的此版本,y是低位字节,为主版本。创建套接字socket (int af, int type, int protocol),第一个参数af是协议的地址族,第二个参数type是协议的套接字类型,此处用的是ICMP协议,应为SOCK_RAW,第三个参数protocol是协议。设置套接口的选项 int PASCAL FAR setsockopt( SOCKET s, int level, int optname,const char FAR* optval, int optlen); s:标识一个套接口的描述字。level:选项定义的层次;目前仅支持SOL_SOCKET和IPPROTO_TCP层次。optname:需设置的选项。optval:指针,指向存放选项值的缓冲区。optlen:optval缓冲区的长度。本程序用来设置发送和接收超时选项。向数据报套接字发送数据Int sendto( SOCKET s ,co ust char FAR *buf, int len, int flags, coust struct sockaddr FAR *to, int toLen );第一个参数是套接字描述符,第二个是指向缓冲区的指针,接下来的两个分别是数据的长度和标志,最后两个参数指定关于目标套接字地址及端口地址的结构和长度。若顺利完成,返回的是实际发送的字节数,若有错误发生,返回的是SOCKET_ERROR,可以通过调用WSAGetLastError()找出具体的代码。其它函数若有错误发生,也是通过调用WSAGetLastError()找出具体的代码从数据报套接字接收数据,int recefrom( SOCKET s ,co ust char FAR *buf, int len, int flags, coust struct sockaddr FAR * from, int FAR *fromlen );参数的说明与sendto()类似。关闭套接字closesocket(SOCKET s);该参数是套接字的选项。应用程序结束后,调用WSACleanup()结束。3.3 编程步骤及流程图实现ping程序的步骤:1). 创建一个AF_INET地址族的SOCK_RAW类型的套接字,同时设定协议IPPROTO_ICMP;2). 创建并初始化ICMP头;3). 调用sendto或WSASendto,将ICMP请求发送给远程主机;4). 调用recvfrom或WSARecvfrom,以接收任何ICMP响应。为了节省空间,将流程图画成如下形式:4. 程序源代码及附加说明本课程设计是在windows界面下实现ping功能,为了使程序的界面简洁和减少一系列繁琐的编程过程,利用AppWizard生成一个基于对话框的MFC应用程序,打开Visual C+ 6.0软件,file-new-project-MFC AppWizard(exe),并在右边输入对文件的命名(ping)和选择存储位置。然后点击确定,在弹出新的对话框中选择基于对话框(dialog based)的类型,再点击“完成(finish)”即可。然后ResourceView中Dialog文件夹中的IDD_PING_DIALOG文件中调整应用程序对话框的大小,并加入两个编辑框,通过右键菜单中的属性可以改变其属性,输入所对应框是用来获取输入的,且字符数不多,可以不改变,而用来显示输出结果的建议在原来的基础上将其styles在多行,水平、竖直滚动条、只读等选项打上勾,其余根据需要设定;并加上两个静态文本框,改变其标题值,通过右击菜单中的属性;整个对话框的名字也是这样设定的。并为“确定”按钮添加OnOk()函数,通过双击“确定”按钮,弹出对话框可以改变关联的函数名,再点击“确定”完成。同理,为“取消”按钮添加单击响应事件。下图分别为编辑框的属性选项和对话框。在AppWizard和ClassWizard自动生成代码的基础上加入必需的代码,来完成ping的功能。在ping.h中加入宏变量和变量定义,IP数据报报头格式、ICMP报文报头格式、IP选项格式的结构体。#include #include / #pragma comment(lib,ws2_32.lib) /链接到库文件#define IP_RECORD_ROUTE 0x7#define DEF_PACKET_SIZE 32 /缺省的ICMP数据报长度#define MAX_PACKET 1024 / 最大ICMP包长度#define MAX_IP_HDR_SIZE 60 / Max IP header size w/options#define ICMP_ECHO 8 /请求回应报文的类型#define ICMP_ECHOREPLY 0 /响应应答报文的类型#define ICMP_MIN 8 /最小ICMP包长度(报头)typedef struct _iphdr /IP数据报头部 unsigned int h_len:4; / Length of the header 位域,占4比特 unsigned int version:4; / Version of IP unsigned char tos; / Type of service unsigned short total_len; / Total length of the packet unsigned short ident; / Unique identifier unsigned short frag_and_flags; / Flags unsigned char ttl; / Time to live unsigned char proto; / Protocol (TCP, UDP etc) unsigned short checksum; / IP checksum unsigned int sourceIP; unsigned int destIP; IpHeader;typedef struct _icmphdr/ICMP报文头部 BYTE i_type; BYTE i_code; / Type sub code USHORT i_cksum; USHORT i_id; USHORT i_seq; ULONG timestamp; IcmpHeader;typedef struct _ipoptionhdr / IP option header - use with socket option IP_OPTIONS/ unsigned char code; / Option type unsigned char len; / Length of option hdr unsigned char ptr; / Offset into options unsigned long addr9; / List of IP addrs IpOptionHeader;class CPing/声明一个类,将变量和对变量的操作封装起来public: void SetConfigure(char* host,int state1=0, int state2=0,int size=DEF_PACKET_SIZE);void Cleanup();void Ping(int timeout =1000);CString m_result;char *host,*address; BOOL route; int icmpcount;private: int DecodeICMPHeader(char *buf, int bytes, SOCKADDR_IN *from, int j);USHORT checksum(USHORT *buffer, int size);void FillICMPData(char *icmp_data, int datasize);void DecodeIPOptions(char *buf, int bytes);SOCKET m_hSocket;IpOptionHeader m_ipopt;SOCKADDR_IN m_addrDest;SOCKADDR_IN m_addrFrom;char *icmp_data; char *recvbuf;USHORT seq_no ;char *lpdest ;int datasize; char buffer0200;在class CPingDlg : public CDialog类中添加两个成员变量 CPing object; CString m_con;其中CPing object是CPing的对象,包含变量和对变量的操作,CString m_con是CString的对象,用来存放ping命令结果。在文件ping.cpp中详细定义CPing类的成员函数。SetConfigure(),是用来初始化一些参数,并得到输入的字符,即远程主机的标识。其中用到的void ZeroMemory(PVOID Destination, SIZE_T Length); 第一个参数指向一块准备用0来填充的内存区域的开始地址,第二个参数为用0来填充的内存区域的大小,按字节来计算。void CPing:SetConfigure(char * host,int state1,int state2,int size)static int n=0;if(lpdest)lpdest=NULL; datasize = size; lpdest = new char strlen(host)+1;ZeroMemory(lpdest,sizeof(lpdest); /将lpdest所指向的内存空间用0填充if(n=0|state=1) / n为0或者state为1,即选择清空时,ping结果的编辑框无显示,便将报文序号重新从0开始计数/m_result=;seq_no=0;wsprintf(buffer0,ping %s rnrn,host);m_result+=buffer0;strcpy(lpdest,host);n+; route=state2;下面Checksum()函数是计算校验和,计算方法是:将数据以字为单位累加到一个双字中,如果数据长度为奇数,最后一个字节被扩展到字,累加的结果是双字,最后将这个双字的高16位和低16位相加后取反,便得到了校验和。USHORT CPing:checksum(USHORT *buffer, int size) unsigned long cksum=0; while (size 1) cksum += *buffer+; size -= sizeof(USHORT); if (size) cksum += *(UCHAR*)buffer;/UCHAR为一个字节, USHORT为两个字节 cksum = (cksum 16) + (cksum & 0xffff); cksum += (cksum 16); return (USHORT)(cksum);FillICMPData()是完成ICMP数据头部的构造,初始化ICMP数据报。void CPing:FillICMPData(char *icmp_data, int datasize) IcmpHeader *icmp_hdr = NULL; char *datapart = NULL; icmp_hdr = (IcmpHeader*)icmp_data; icmp_hdr-i_type = ICMP_ECHO; / Request an ICMP echo icmp_hdr-i_code = 0;icmp_hdr-i_id = (USHORT)GetCurrentProcessId();/表示发送ICMP数据报的应用程序ID icmp_hdr-i_cksum = 0; icmp_hdr-i_seq = 0; datapart = icmp_data + sizeof(IcmpHeader); /数据部分的起始地址DecodeIPOptions()是用来解析IP选项的。void CPing:DecodeIPOptions(char *buf, int bytes) /解析IP选项 IpOptionHeader *ipopt = NULL; IN_ADDR inaddr; HOSTENT *host = NULL; ipopt = (IpOptionHeader *)(buf + 20); /IP首部的字节数为20 m_result+=Ping 结果: rn; for(int t = 0; tptr / 4) - 1; t+) inaddr.S_un.S_addr = ipopt-addrt; host=gethostbyaddr(char*)&inaddr.S_un.S_addr,sizeof(inaddr.S_un.S_addr),AF_INET); if (host)wsprintf(buffer0,(%-15s) %s rn, inet_ntoa(inaddr), host-h_name); m_result+=buffer0;return; elsewsprintf(buffer0,(%-15s)rn, inet_ntoa(inaddr);m_result+=buffer0;return; DecodeICMPHeader()是用来解析ICMP报文的,解释详见程序。int CPing:DecodeICMPHeader(char *buf, int bytes, SOCKADDR_IN *from, int j) IpHeader *iphdr = NULL; IcmpHeader *icmphdr = NULL; unsigned short iphdrlen; DWORD endtime; iphdr = (IpHeader *)buf;/ Number of 32-bit words * 4 = bytes iphdrlen = iphdr-h_len * 4;endtime = GetTickCount();/判断是否含IP首先选项,并进行调用相应的函数进行处理。 if(iphdrlen = MAX_IP_HDR_SIZE) & (!icmpcount) DecodeIPOptions(buf, bytes);/对不符合最小长度给出提示,并结束,而最大长度由recvfrom()函数决定,/并根据返回的值判定是否出错。 if (bytes sin_addr);m_result+=buffer0;return j; /icmp头部在IP数据报报头之后,跳过IP报头的字节,/指针icmphdr指向ICMP报文头的起始位置icmphdr = (IcmpHeader*)(buf + iphdrlen);/根据ICMP报文头的类型值判断是否为应答回显报文 if (icmphdr-i_type != ICMP_ECHOREPLY) wsprintf(buffer0,not echo type %d recvd rn, icmphdr-i_type);m_result+=buffer0; return j; / 确保接收到ICMP报文是本应用程序发送请求回显ICMP报文的应答,收到icmp报文/的ID与发送icmp报文的应用程序的ID 一致,若不一致,输出字符以提示 if (icmphdr-i_id != (USHORT)GetCurrentProcessId() char buffer0100;sprintf(buffer0, someone elses packet! rn);m_result+=buffer0;return j; j+; /统计正确接收报文的次数/存储ping命令的结果,包括远程主机的IP地址、序号、所用时间。wsprintf(buffer0,%dbytes reply from %s:, bytes,inet_ntoa(from-sin_addr) ); m_result+=buffer0;wsprintf(buffer0, seq=%d., icmphdr-i_seq);m_result+=buffer0;wsprintf(buffer0,time=%dmsrn, endtime - icmphdr-timestamp);m_result+=buffer0;icmpcount+; return j;Ping()相当于主程序,用来实现ping命令的核心程序,包括创建套接字,设置套接字的选项,发送和接收ICMP报文,及一系列相关的处理等。首先简单介绍几个结构体和函数。结构体sockaddr_instruct sockaddr_in short int sin_family; unsigned short int sin_port; struct in_addr sin_addr; unsigned char sin_zero8;其中sin_family指代协议族,在socket编程中只能是AF_INET,sin_port存储端口号(使用网络字节顺序),sin_addr存储IP地址,使用in_addr数据结构,sin_zero是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节。s_addr按照网络字节顺序存储IP地址。结构体 struct hostent char FAR *h_name; char FAR * FAR *h_aliases; short h_addrtype; short h_length; char FAR * FAR *h_addr_list;其中h_name为正规的主机名字(PC),h_aliases一个以空指针结尾的可选主机名队列,h_addrtype返回地址的类型,对于Windows Sockets,这个域总是PF_INET。h_legnth为每个地址的长度(字节数),对应于PF_INET这个域应该为4。h_addr_list为以空指针结尾的主机地址的列表,返回的地址是以网络顺序排列的,为保证其他旧的软件的兼容性,h_addr_list0被定义为宏h_addr。函数inet_addr()将一个点间隔地址转换成一个in_addr结构的地址。inet_ntoa(),将网络地址转换成“.”点隔的字符串格式。gethostbyname()将指向主机名的指针转换成对应于给定主机名的包含主机名字和地址信息的hostent结构指针。以下为Ping()函数。#define TIME 4 /连续发送ICMP报文的次数void CPing:Ping(int timeout) m_hSocket = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); if (m_hSocket = INVALID_SOCKET) m_result+=socket(),创建套接字失败!; return ; if (route) / Setup the IP option header to go out on every ICMP packet ZeroMemory(&m_ipopt, sizeof(m_ipopt); m_ipopt.code = IP_RECORD_ROUTE; / Record route option m_ipopt.ptr = 4; / Point to the first addr offset m_ipopt.len = 39; / Length of option header int ret = setsockopt(m_hSocket, IPPROTO_IP, IP_OPTIONS, (char *)&m_ipopt, sizeof(m_ipopt); if (ret = SOCKET_ERROR) m_result+=IP选项头,设置socket协议选项错误!; return; / Set the send/recv timeout values int bread = setsockopt(m_hSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout); if(bread = SOCKET_ERROR) m_result+=setsockopt(),设置socket接收超时选项错误!; return ; timeout = 1000; bread = setsockopt(m_hSocket, SOL_SOCKET, SO_SNDTIMEO,(char*)&timeout, sizeof(timeout); if (bread = SOCKET_ERROR) m_result+=setsockopt(),设置socket发送超时选项错误!; return ; memset(&m_addrDest, 0, sizeof(m_addrDest); /清空地址区域 / Resolve the endpoints name if necessary m_addrDest.sin_family = AF_INET; if (m_addrDest.sin_addr.s_addr = inet_addr(lpdest) = INADDR_NONE) struct hostent *hp = NULL; if (hp = gethostbyname(lpdest) != NULL) memcpy(&(m_addrDest.sin_addr), hp-h_addr, hp-h_length); m_addrDest.sin_family = hp-h_addrtype; else m_result+=未能找到你所输入的主机,请仔细检查您的输入rn并确定网络已连接好再尝试!; return ; / Create the ICMP packet datasize += sizeof(IcmpHeader); icmp_data =(char*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PACKET); recvbuf =(char*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,MAX_PACKET); if (!icmp_data) m_result+=HeapAlloc()堆分配错误!; return ; memset(icmp_data,0,MAX_PACKET); FillICMPData(icmp_data,datasize); / Start sending/receiving ICMP packetsint nCount=0, icmpcount=0,i=0,j=0; while(1) int bwrote; if (nCount+ = TIME) wsprintf(buffer0,rnping stastistics for %s rn packets number:sent = %d received = %d lost = %d rn,inet_ntoa( (SOCKADDR_IN *)&m_addrDest)-sin_addr),TIME-i,j,TIME-i-j); m_result+=buffer0;if(j=0) m_result+=rn远程主机不可达!rn; break; (IcmpHeader*)icmp_data)-i_cksum = 0; (IcmpHeader*)icmp_data)-timestamp = GetTickCount(); (IcmpHeader*)icmp_data)-i_seq = seq_no+; (IcmpHeader*)icmp_data)-i_cksum=checksum(USHORT*)icmp_data,datasize); bwrote = sendto(m_hSocket, icmp_data, datasize, 0, (struct sockaddr*)&m_addrDest, sizeof(m_addrDest); if (bwrote = SOCKET_ERROR) if (WSAGetLastError() = WSAETIMEDOUT) m_result+=send time out !rn; i+; continue; return ; if (bwrote “建立类向导”,或使用快捷菜单Ctrl+W,在弹出的对话框中的选项卡中选择“成员变量”,再选择右边的“添加变量 (add variable)”,再在弹出的对话框中输入相应的变量名和选择需要的变量类型等。图示如下:二是通过函数来控制,分别是GetDlgItemText()和SetDlgItemText()来实现两者间的传递。本程序用的是第二种方法,第一种方法如程序中的注释。void CPingDlg:OnOk() / TODO: Add your control notification handler code here WSADATA wsadata; /初始化 WSAStartup(MAKEWORD(2,2),&wsadata); CButton* checkbox=(CButton*)GetDlgItem(IDC_CHECK1);int state=checkbox-GetCheck(); CButton* checkbox2=(CButton*)GetDlgItem(IDC_CHECK2);int state2=checkbox2-GetCheck(); / UpdateData(true); char host100;GetDlgItemText (IDC_EDIT1,host,100); object.icmpcount=0;object.SetConfigure(host,state,DEF_PACKET_SIZE);object.Ping();object.m_result+=rnrn-rnrn;m_con=object.m_result; SetDlgItemText(IDC_EDIT2,m_con); /m_con1=object.m_result; UpdateData(false); object.Cleanup(); /结束处理这就完成了具有ping命令功能程序代码的编辑。5. 运行结果运行程序,在编译和构建源程序后执行可执行文件。5.1 ping 主机名 5.2 ping 域名 5.3 ping IP地址 记录了路由的ping命令的结果如下图。6. 遇到问题及解决方法1). VC+编译时出现下列错误:这是因为虽然包含了的头文件,在使用中,但却没有把库文件ws2_32.lib作为项目的非缺省的链接库包含到项目文件中去,因此将项目必须链接ws2_32.lib这个库文件。链接到库文件的做法是在菜单project- setting-link-Object/library 下面的编辑框中加上WS2_32.LIB,或者在程序开头部分加入指令#pragma comment(lib,ws2_32.lib)将项目链接到库文件。2). 运行过程中,本不应出现错误返回的函数出现了错误返回。例如获取所输入的主机信息,输入主机标识正确,但却无法返回正确的包含主机和地址信息hostent结构指针,这是因为一些函数的调用都要先初始化Winsock,调用WSAStartup()函数。如函数gethostbyname()的调用就需要先调用WSAStartup()函数。我们可以通过用函数WSAGetLastError()来得到一个特定的错误代码,若返回WSANOTINTIALISED,则说明在应用这个API前,没有成功地调用WSAStartup()。3).建立基于对话框的应用程序时,若用对话框中本来含有的“确定”按钮而得到单击响应事件BN_CLICKED的函数,运行时在点击“确定”按钮后会退出对话框窗口,本文不希望出现这种情况,方法是把程序后面的CDialog: OnOk();去掉,或在前面加上两斜杠/,表示注释。4). 希望在选择“取消”时,弹出一个告诉运行者是否真得要退出的窗口,可以在pingDlg.cpp文件中的void CPingDlg:OnCancel() 函数中加上if(AfxMessageBox(确定要退出窗口吗?,MB_YESNO)=IDYES)或加上if(MessageBox(确定要退出窗口吗?,ping,MB_YESNO)=IDYES),两者实现的效果差不多,后者是CWnd类的成员函数。7.附加功能 1). 为了windows界面的美观,可以增加一些附加程序。如对话框的颜色太单调,黑白显示的,若想根据自己的喜好改变对话框背景颜色和静态文本框或只用来显示(read-only)的编辑框文字颜色,可在ping.cpp文件中的BOOL CPingApp:InitInstance() 加上语句SetDialogBkColor (RGB (180,255,250), RGB(0,0,0); 第一个参数为对话框背景的颜色,第二个参数为文字的颜色,RGB()中的参数值根据需要而定。也可以改变控件的颜色及控件中文字的颜色、大小、字体等等,通过在消息映射下添加ON_WM_CTLCOLOR()消息,即在处理类中添加了OnCtlColor()方法,再在其中编辑函数实现;另外要附加说明的是,这种方法不适用于按钮控件,按钮的改变的实现比较复杂,需要新建以CButton基类的派生类重新绘制,并将在数据交换的处理函数void CPingDlg:DoDataExchange(CDataExchange* pDX)中将按钮的ID与控制变量对应,采取的方法是通过添加语句DDX_Control(pDX, 按钮ID, 控制变量)。但这种方法比较适用于多媒体类的软件,增添色彩和艺术感。此处是黑白打印,故不给出运行结果图。2).本文想设计一个具有查询本地主机名和IP地址的功能。本文件将查询功能和ping功能放在同一个对话框显示,因此这时比较适合用创建属性表和属性页来实现,实现查询功能的程序为:WSADATA wsaData;WSAStartup(MAKEWORD(1,1),&wsaData);char HostName128;if( gethostname(HostName, 128) = 0 )/ Get host adressesm_hostname.SetWindowText(HostName);struct hostent * Host;in
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 老年人友善医疗机构认证标准
- 2023年电商平台客户服务解决方案
- 中国传统文化元素与现代设计融合
- 护理计划制定与有效执行指南
- 文学作品教学反思与教学方法创新
- 诫子书古文教学设计详解
- 高校学生心理咨询实务及案例分析
- 2025年煤矿安全培训安全培训安全培训安全评价人员安全培训试卷及答案
- 儿童识字游戏创意设计与应用
- 2025年煤矿应急演练评估安全培训试卷及答案:应急演练的演练反馈与交流技巧测试
- 品质意识培训内容
- 部队司务长基础知识培训课件
- 美团代运营入门知识培训
- 2025年电力行业安全生产考试题库(规范试题)试卷(含答案)
- DB51-T 3285-2025 染色体畸变和微核检测质量控制规范
- 2025年辽宁省中小学教师招聘考试真题及答案
- 江浙皖高中(县中)发展共同体2025-2026学年高三上学期10月联考化学试题(含答案)
- 《城镇供水管道用阀门应用技术规程》
- 高职教师职业转型培训方案
- 躯体症状及相关障碍课件
- 脓毒性休克相关课件
评论
0/150
提交评论