ping and traceroute(tracert)
1、ping程序简单介绍
这个程序是Mike Muuss编写的。目的是測试另外一台机子是否可达。
运用的协议就是ICMP。运用的是ICMP的回显应答和请求回显两个类型。曾经呢。能ping通说明可以进行比方ftp。telnet等操作,不能ping通就不能做这种操作。
可是发展到如今。这个关系已经不成立了。非常多防火墙都可以屏蔽掉ping。
ICMP请求和回显报文格式:(图片是网上下载的一个)
能够看清楚当中的内容,ICMP报文格式太多了。所以针对的来说说。这个就是ping程序使用的ICMP报文。
注意当中几点:
第一、一般实现来说。ICMP报文中的标识符设置成发送进程的ID,这样即使一台机执行多个ping程序也不会混乱(unix就是这么做的。
)。
第二、客户发送的选项数据。必须回显。
这个我想我们ping一个IP地址。返回的内容非常多。比方:
回显的内容有字节,时间。ttl等。
这个有什么用。
计算时间就是一个样例:
ping计算时间是依据ICMP报文中存放的发送请求的时间来计算往返时间的。也就是说并非我们会自己记录一个时间。当应答返回。用当前时间减去ICMP报文中的时间值,就是往返时间。
对于ping,我们看到的是一个顺序的输出。req为1的在req为2的前面。可是实际上也可能出现同样的分组序号,还有N+1的序号在N之前的。这都可能出现,尤其是在广域网中进行ping。
ping提供了一个-R选项,提供记录路由功能。
记录路由功能就是将途经的路由器地址增加到IP数据包中。最多仅仅能放9个IP地址。由于首部长度60byte。IP头部20byte,减去3byte的路由记录功能的选项(也就是一些控制字段,比方类型。长度,指针)。剩下37bytes。仅仅能放9个IP地址了。
注意这个路由记录功能仅仅是记录出口IP地址。比方一个路由有2个IP地址链接两个不同的网络。记录仅仅是记录出口的IP地址。出。
最新的win8系统不支持-R选项。
ping是不经过TCP/UDP的。
2、traceroute\tracert
原理:
当路由器接受到一个IP数据包的时候,假设TLL为0或1就不转发该数据包,并给信息源发送一个ICMP超时信息。
这个ICMP信息的IP报文的信源地址是该路由器的IP地址(这是traceroute的关键)。
traceroute的做法是:
发送一个TTL为1的IP数据包给目的主机,处理这个数据包的第一个路由器将TTL减去1。丢弃数据包,并发送ICMP超时。这样就得到第一个路由器的IP地址了(这个在ICMP数据中有)。然后traceroute继续发送TTL为2的数据包给目的地址。这样就能够得到第二个路由IP。一直继续。那么怎么推断数据包到了目的地呢??
Traceroute程序发送IP数据包是包括UDP数据,可是udp选择一个不可能的值作为udpport,使不论什么一个应用都不可能使用该port。那么到达目的地的时候,主机将产生一个port不可达的ICMP错误。这样就能够通过推断返回的ICMP错误类型知道是否已经达到目的地了。
注意了。这个traceroute计算时间的跟ping不一样。traceroute是保存了数据包发送的时间。当收到一个icmp数据包的时候,得到系统当前时间,减去之前保存的时间就是RTT时间。
ping是在回显中存储了时间。所以ping更加可以准确。
为什么traceroute没有跟ping一样呢,由于ICMP仅仅返回出错的IP数据包的前8个字节,这8个字节就是udp的头部。因此没有返回traceroute存储的时间。
ICMP这个协议是IP的附属协议。由于它是用来控制差错的。所以很实用。
这个协议也是很复杂的。
附录:
以下来一个ping的源码。在linux 下执行(我是没有执行成功)
/*
* P I N G . C
*
* Using the InterNet Control Message Protocol (ICMP) "ECHO" facility,
* measure round-trip-delays and packet loss across network paths.
*
* Author -
* Mike Muuss
* U. S. Army Ballistic Research Laboratory
* December, 1983
* Modified at Uc Berkeley
*
* Changed argument to inet_ntoa() to be struct in_addr instead of u_long
* DFM BRL 1992
*
* Status -
* Public Domain. Distribution Unlimited.
*
* Bugs -
* More statistics could always be gathered.
* This program has to run SUID to ROOT to access the ICMP socket.
*/ #include <stdio.h>
#include <errno.h>
#include <sys/time.h> #include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/file.h> #include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netdb.h> #define MAXWAIT 10 /* max time to wait for response, sec. */
#define MAXPACKET 4096 /* max packet size */
#define VERBOSE 1 /* verbose flag */
#define QUIET 2 /* quiet flag */
#define FLOOD 4 /* floodping flag */
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif u_char packet[MAXPACKET];
int i, pingflags, options;
extern int errno; int s; /* Socket file descriptor */
struct hostent *hp; /* Pointer to host info */
struct timezone tz; /* leftover */ struct sockaddr whereto;/* Who to ping */
int datalen; /* How much data */ char usage[] =
"Usage: ping [-dfqrv] host [packetsize [count [preload]]]\n"; char *hostname;
char hnamebuf[MAXHOSTNAMELEN]; int npackets;
int preload = 0; /* number of packets to "preload" */
int ntransmitted = 0; /* sequence # for outbound packets = #sent */
int ident; int nreceived = 0; /* # of packets we got back */
int timing = 0;
int tmin = 999999999;
int tmax = 0;
int tsum = 0; /* sum of all times, for doing average */
int finish(), catcher();
char *inet_ntoa(); /*
* M A I N
*/
main(argc, argv)
char *argv[];
{
struct sockaddr_in from;
char **av = argv;
struct sockaddr_in *to = (struct sockaddr_in *) &whereto;
int on = 1;
struct protoent *proto; argc--, av++;
while (argc > 0 && *av[0] == '-') {
while (*++av[0]) switch (*av[0]) {
case 'd':
options |= SO_DEBUG;
break;
case 'r':
options |= SO_DONTROUTE;
break;
case 'v':
pingflags |= VERBOSE;
break;
case 'q':
pingflags |= QUIET;
break;
case 'f':
pingflags |= FLOOD;
break;
}
argc--, av++;
}
if(argc < 1 || argc > 4) {
printf(usage);
exit(1);
} bzero((char *)&whereto, sizeof(struct sockaddr) );
to->sin_family = AF_INET;
to->sin_addr.s_addr = inet_addr(av[0]);
if(to->sin_addr.s_addr != (unsigned)-1) {
strcpy(hnamebuf, av[0]);
hostname = hnamebuf;
} else {
hp = gethostbyname(av[0]);
if (hp) {
to->sin_family = hp->h_addrtype;
bcopy(hp->h_addr, (caddr_t)&to->sin_addr, hp->h_length);
hostname = hp->h_name;
} else {
printf("%s: unknown host %s\n", argv[0], av[0]);
exit(1);
}
} if( argc >= 2 )
datalen = atoi( av[1] );
else
datalen = 64-8;
if (datalen > MAXPACKET) {
fprintf(stderr, "ping: packet size too large\n");
exit(1);
}
if (datalen >= sizeof(struct timeval)) /* can we time 'em? */
timing = 1; if (argc >= 3)
npackets = atoi(av[2]); if (argc == 4)
preload = atoi(av[3]); ident = getpid() & 0xFFFF; if ((proto = getprotobyname("icmp")) == NULL) {
fprintf(stderr, "icmp: unknown protocol\n");
exit(10);
} if ((s = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) {
perror("ping: socket");
exit(5);
}
if (options & SO_DEBUG) {
if(pingflags & VERBOSE)
printf("...debug on.\n");
setsockopt(s, SOL_SOCKET, SO_DEBUG, &on, sizeof(on));
}
if (options & SO_DONTROUTE) {
if(pingflags & VERBOSE)
printf("...no routing.\n");
setsockopt(s, SOL_SOCKET, SO_DONTROUTE, &on, sizeof(on));
} if(to->sin_family == AF_INET) {
printf("PING %s (%s): %d data bytes\n", hostname,
inet_ntoa(to->sin_addr), datalen); /* DFM */
} else {
printf("PING %s: %d data bytes\n", hostname, datalen );
}
setlinebuf( stdout ); signal( SIGINT, finish );
signal(SIGALRM, catcher); /* fire off them quickies */
for(i=0; i < preload; i++)
pinger(); if(!(pingflags & FLOOD))
catcher(); /* start things going */ for (;;) {
int len = sizeof (packet);
int fromlen = sizeof (from);
int cc;
struct timeval timeout;
int fdmask = 1 << s; timeout.tv_sec = 0;
timeout.tv_usec = 10000; if(pingflags & FLOOD) {
pinger();
if( select(32, &fdmask, 0, 0, &timeout) == 0)
continue;
}
if ( (cc=recvfrom(s, packet, len, 0, &from, &fromlen)) < 0) {
if( errno == EINTR )
continue;
perror("ping: recvfrom");
continue;
}
pr_pack( packet, cc, &from );
if (npackets && nreceived >= npackets)
finish();
}
/*NOTREACHED*/
} /*
* C A T C H E R
*
* This routine causes another PING to be transmitted, and then
* schedules another SIGALRM for 1 second from now.
*
* Bug -
* Our sense of time will slowly skew (ie, packets will not be launched
* exactly at 1-second intervals). This does not affect the quality
* of the delay and loss statistics.
*/
catcher()
{
int waittime; pinger();
if (npackets == 0 || ntransmitted < npackets)
alarm(1);
else {
if (nreceived) {
waittime = 2 * tmax / 1000;
if (waittime == 0)
waittime = 1;
} else
waittime = MAXWAIT;
signal(SIGALRM, finish);
alarm(waittime);
}
} /*
* P I N G E R
*
* Compose and transmit an ICMP ECHO REQUEST packet. The IP packet
* will be added on by the kernel. The ID field is our UNIX process ID,
* and the sequence number is an ascending integer. The first 8 bytes
* of the data portion are used to hold a UNIX "timeval" struct in VAX
* byte-order, to compute the round-trip time.
*/
pinger()
{
static u_char outpack[MAXPACKET];
register struct icmp *icp = (struct icmp *) outpack;
int i, cc;
register struct timeval *tp = (struct timeval *) &outpack[8];
register u_char *datap = &outpack[8+sizeof(struct timeval)]; icp->icmp_type = ICMP_ECHO;
icp->icmp_code = 0;
icp->icmp_cksum = 0;
icp->icmp_seq = ntransmitted++;
icp->icmp_id = ident; /* ID */ cc = datalen+8; /* skips ICMP portion */ if (timing)
gettimeofday( tp, &tz ); for( i=8; i<datalen; i++) /* skip 8 for time */
*datap++ = i; /* Compute ICMP checksum here */
icp->icmp_cksum = in_cksum( icp, cc ); /* cc = sendto(s, msg, len, flags, to, tolen) */
i = sendto( s, outpack, cc, 0, &whereto, sizeof(struct sockaddr) ); if( i < 0 || i != cc ) {
if( i<0 ) perror("sendto");
printf("ping: wrote %s %d chars, ret=%d\n",
hostname, cc, i );
fflush(stdout);
}
if(pingflags == FLOOD) {
putchar('.');
fflush(stdout);
}
} /*
* P R _ T Y P E
*
* Convert an ICMP "type" field to a printable string.
*/
char *
pr_type( t )
register int t;
{
static char *ttab[] = {
"Echo Reply",
"ICMP 1",
"ICMP 2",
"Dest Unreachable",
"Source Quench",
"Redirect",
"ICMP 6",
"ICMP 7",
"Echo",
"ICMP 9",
"ICMP 10",
"Time Exceeded",
"Parameter Problem",
"Timestamp",
"Timestamp Reply",
"Info Request",
"Info Reply"
}; if( t < 0 || t > 16 )
return("OUT-OF-RANGE"); return(ttab[t]);
} /*
* P R _ P A C K
*
* Print out the packet, if it came from us. This logic is necessary
* because ALL readers of the ICMP socket get a copy of ALL ICMP packets
* which arrive ('tis only fair). This permits multiple copies of this
* program to be run without having intermingled output (or statistics!).
*/
pr_pack( buf, cc, from )
char *buf;
int cc;
struct sockaddr_in *from;
{
struct ip *ip;
register struct icmp *icp;
register long *lp = (long *) packet;
register int i;
struct timeval tv;
struct timeval *tp;
int hlen, triptime; from->sin_addr.s_addr = ntohl( from->sin_addr.s_addr );
gettimeofday( &tv, &tz ); ip = (struct ip *) buf;
hlen = ip->ip_hl << 2;
if (cc < hlen + ICMP_MINLEN) {
if (pingflags & VERBOSE)
printf("packet too short (%d bytes) from %s\n", cc,
inet_ntoa(ntohl(from->sin_addr))); /* DFM */
return;
}
cc -= hlen;
icp = (struct icmp *)(buf + hlen);
if( (!(pingflags & QUIET)) && icp->icmp_type != ICMP_ECHOREPLY ) {
printf("%d bytes from %s: icmp_type=%d (%s) icmp_code=%d\n",
cc, inet_ntoa(ntohl(from->sin_addr)),
icp->icmp_type, pr_type(icp->icmp_type), icp->icmp_code);/*DFM*/
if (pingflags & VERBOSE) {
for( i=0; i<12; i++)
printf("x%2.2x: x%8.8x\n", i*sizeof(long),
*lp++);
}
return;
}
if( icp->icmp_id != ident )
return; /* 'Twas not our ECHO */ if (timing) {
tp = (struct timeval *)&icp->icmp_data[0];
tvsub( &tv, tp );
triptime = tv.tv_sec*1000+(tv.tv_usec/1000);
tsum += triptime;
if( triptime < tmin )
tmin = triptime;
if( triptime > tmax )
tmax = triptime;
} if(!(pingflags & QUIET)) {
if(pingflags != FLOOD) {
printf("%d bytes from %s: icmp_seq=%d", cc,
inet_ntoa(from->sin_addr),
icp->icmp_seq ); /* DFM */
if (timing)
printf(" time=%d ms\n", triptime );
else
putchar('\n');
} else {
putchar('\b');
fflush(stdout);
}
}
nreceived++;
} /*
* I N _ C K S U M
*
* Checksum routine for Internet Protocol family headers (C Version)
*
*/
in_cksum(addr, len)
u_short *addr;
int len;
{
register int nleft = len;
register u_short *w = addr;
register u_short answer;
register int sum = 0; /*
* Our algorithm is simple, using a 32 bit accumulator (sum),
* we add sequential 16 bit words to it, and at the end, fold
* back all the carry bits from the top 16 bits into the lower
* 16 bits.
*/
while( nleft > 1 ) {
sum += *w++;
nleft -= 2;
} /* mop up an odd byte, if necessary */
if( nleft == 1 ) {
u_short u = 0; *(u_char *)(&u) = *(u_char *)w ;
sum += u;
} /*
* add back carry outs from top 16 bits to low 16 bits
*/
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return (answer);
} /*
* T V S U B
*
* Subtract 2 timeval structs: out = out - in.
*
* Out is assumed to be >= in.
*/
tvsub( out, in )
register struct timeval *out, *in;
{
if( (out->tv_usec -= in->tv_usec) < 0 ) {
out->tv_sec--;
out->tv_usec += 1000000;
}
out->tv_sec -= in->tv_sec;
} /*
* F I N I S H
*
* Print out statistics, and give up.
* Heavily buffered STDIO is used here, so that all the statistics
* will be written with 1 sys-write call. This is nice when more
* than one copy of the program is running on a terminal; it prevents
* the statistics output from becomming intermingled.
*/
finish()
{
putchar('\n');
fflush(stdout);
printf("\n----%s PING Statistics----\n", hostname );
printf("%d packets transmitted, ", ntransmitted );
printf("%d packets received, ", nreceived );
if (ntransmitted)
if( nreceived > ntransmitted)
printf("-- somebody's printing up packets!");
else
printf("%d%% packet loss",
(int) (((ntransmitted-nreceived)*100) /
ntransmitted));
printf("\n");
if (nreceived && timing)
printf("round-trip (ms) min/avg/max = %d/%d/%d\n",
tmin,
tsum / nreceived,
tmax );
fflush(stdout);
exit(0);
}
//E*O*F ping.c//
给一个可以在windows下执行成功的ping。这个ping是别人写的,时间计算等跟官方的不一样,可是也可以执行得到结果。仅供參考。
// ping.cpp : 定义控制台应用程序的入口点。
//
/*
改程序ping自己和ping一些内网不存在IP,不会经过wireshark
*/
#include <tchar.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32")
#include <stdio.h>
#include <string.h>
#include "Ws2tcpip.h"
typedef struct icmp_hdr
{
unsigned char icmp_type; // 类型
unsigned char icmp_code; // 代码
unsigned short icmp_checksum; // 校验和
//以下内容对于不同类型和代码有不同的内容
unsigned short icmp_id; // 标识符
unsigned short icmp_sequence; // 序列号
//以下是选项数据
unsigned long icmp_timestamp; // 时间戳
} ICMP_HDR, *PICMP_HDR; typedef struct _IPHeader // 20字节的IP头
{
UCHAR iphVerLen; // 版本和头长度(各占4位)
UCHAR ipTOS; // 服务类型
USHORT ipLength; // 封包总长度,即整个IP报的长度
USHORT ipID; // 封包标识。惟一标识发送的每个数据报
USHORT ipFlags; // 标志
UCHAR ipTTL; // 生存时间,就是TTL
UCHAR ipProtocol; // 协议。可能是TCP、UDP、ICMP等
USHORT ipChecksum; // 校验和
ULONG ipSource; // 源IP地址
ULONG ipDestination; // 目标IP地址
} IPHeader, *PIPHeader; USHORT checksum(USHORT* buff, int size)
{
unsigned long cksum = 0;
while(size>1)
{
cksum += *buff++;
size -= sizeof(USHORT);
}
// 是奇数
if(size)
{
cksum += *(UCHAR*)buff;
}
// 将32位的chsum高16位和低16位相加,然后取反
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >> 16);
return (USHORT)(~cksum);
} int main(int argc, char* argv[])
{
// Validate the parameters
if (argc != 2) {
printf("usage: %s ipv4 address\n", argv[0]);
printf(" to return the host\n");
printf(" %s 127.0.0.1\n", argv[0]);
return 1;
} WSADATA wsaData;
WORD sockVersion = MAKEWORD(2, 2);
//载入winsock库
if(WSAStartup(sockVersion, &wsaData) != 0)
return 0;
//建立原始套接字
SOCKET sRaw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
//超时时间
int OutTime=100;
//设置超时
setsockopt(sRaw, IPPROTO_IP, IP_TTL, (char*)&OutTime, sizeof(OutTime)); SOCKADDR_IN dest;
dest.sin_family = AF_INET;
dest.sin_port = htons(0); //填写ping主机地址
char *host_name = argv[1]; // If the user input is an alpha name for the host, use gethostbyname()
// If not, get host by addr (assume IPv4)
printf("ping %s...\n", host_name);
if (isalpha(host_name[0]))
{ /* host address is a name */
struct hostent *remoteHost = gethostbyname(host_name);//能够ping域名
dest.sin_addr.S_un.S_addr = *(u_long *) remoteHost->h_addr_list[0];
}
else
dest.sin_addr.S_un.S_addr = inet_addr(argv[1]); char buff[sizeof(ICMP_HDR)];
ICMP_HDR* pIcmp = (ICMP_HDR*)buff; char recvBuf[1024]; SOCKADDR_IN from;
int nLen = sizeof(from);
while(TRUE)
{
static int nCount = 0;
int nRet;
if(nCount++ == 4)
break;
//类型8
pIcmp->icmp_type = 8;
//代码0
pIcmp->icmp_code = 0;
//标识符为本进程id
pIcmp->icmp_id = (USHORT)GetCurrentProcessId();
//检验和先填充为0
pIcmp->icmp_checksum = 0;
//时间戳为系统执行时间
pIcmp->icmp_timestamp = GetTickCount();
//计算检验和
pIcmp->icmp_checksum = checksum((USHORT*)buff, sizeof(ICMP_HDR) ); //发送ICMP回显请求数据报
nRet = sendto(sRaw, buff, sizeof(ICMP_HDR) , 0, (SOCKADDR *)&dest, sizeof(dest));
//发送错误。提示并退出程序
if(nRet == SOCKET_ERROR)
{
printf(" sendto failed %d\n",WSAGetLastError());
return 0;
} nRet = recvfrom(sRaw, recvBuf, 1024, 0, (sockaddr*)&from, &nLen);
if(nRet == SOCKET_ERROR)
{
if(WSAGetLastError() == WSAETIMEDOUT)
{
printf(" timed out\n");
continue;
} printf(" recvfrom failed \n");
return 0;
} //得到当前系统执行时间
int nTick = GetTickCount();
//得到IP首部
IPHeader *Iphdr=(IPHeader*)recvBuf;
//推断是其后是否是ICMP报文
if(Iphdr->ipProtocol!=0x01)
{
printf("this is not a icmp packet\n");
return 0;
}
//定位到ICMP报文首部
ICMP_HDR* pRecvIcmp = (ICMP_HDR*)(recvBuf + sizeof(IPHeader));
//推断收到的报文是否和我们发送的报文相相应
if(pRecvIcmp->icmp_id != GetCurrentProcessId())
{
printf("this is another icmp packet\n");
return 0;
}
//输出ping主机的ip
printf("Reply from %s: ",inet_ntoa(from.sin_addr));
//输出收到的字节数
printf("bytes=%d ",nRet);
//输出从发送数据报到收到数据报所经历的时间
printf("time=%dms\n",nTick - pRecvIcmp->icmp_timestamp);
//Sleep(100);
}
return 0;
}
參考书籍:《TCP/IP具体解释卷1》
ping and traceroute(tracert)的更多相关文章
- ping请求超(iPV4)
ping请求超(iPV4) arp –a(查看局域网全部IP) cmd 管理员运行 netsh winsock reset(重置Winsock目录借以恢复网络) etsh int ip reset r ...
- 防火墙设置:虚拟机ping不通主机,但是主机可以ping通虚拟机(转载)
我在Windows7系统安装了虚拟机,通过虚拟机安装了Ubuntu13.04,我设置的主机与虚拟机的连接方式是桥接,安装好后,发现虚拟机ping不通主机,但是主机可以ping通虚拟机. 我的操作是:关 ...
- 虚拟机ping不通主机,但是主机可以ping通虚拟机(转载)
我在Windows7系统安装了虚拟机,通过虚拟机安装了Ubuntu13.04,我设置的主机与虚拟机的连接方式是桥接,安装好后,发现虚拟机ping不通主机,但是主机可以ping通虚拟机. 我的操作是:关 ...
- 两个不同网段的PC直连是否可以Ping通,肯定可以Ping的通(转)
在这一篇文章中http://blog.csdn.net/zhangdaisylove/article/details/46892917的案例,明确的说明两个不同网段的PC不能Ping的通,其实他给出的 ...
- CCNA网络工程师学习进程(3)常规网络设计模型与基本的网络协议
本节介绍分层的网络设计模型与基本的网络协议,包括ARP协议,ICMP协议和IP协议. (1)三层网络架构: 一个好的园区网设计应该是一个分层的设计.一般分为接入层.汇聚层(分布层).核 ...
- scapy学习笔记(5)
1.ACK Scan >>>ans,unans=sr(IP(dst=,],flags="A") 扫描后,若要找出未过虑的端口: for s,r in ans: i ...
- linux学习之centos(二):虚拟网络三种连接方式和SecureCRT的使用
---操作环境--- 虚拟机版本:VMware Workstation_10.0.3 Linux系统版本:CentOS_6.5(64位) 物理机系统版本:win10 一.虚拟网络三种连接方式 当在V ...
- 【ASP.NET Core快速入门】(三)准备CentOS和Nginx环境
基本软件 VMware虚拟机 centos:http://isoredirect.centos.org/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-170 ...
- 菜鸟入门【ASP.NET Core】3:准备CentOS和Nginx环境转(转)
基本软件 VMware虚拟机 centos:http://isoredirect.centos.org/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-170 ...
随机推荐
- [转] 使用CSS3 will-change提高页面滚动、动画等渲染性能 ---张鑫旭
一.先来看一个例子 下面这个例子来自某外文,我这里简单转述下. 视差滚动现在不是挺流行的嘛,然后Chris Ruppel当其使用background-attachment: fixed实现背景图片不随 ...
- mysql数据类型——整型INT(m)
1.整形分为四种 tinyint smallint mediumint int bigint 注意: 右侧的取值范围是在未加unsigned关键字的情况下,如果加了unsigned,则最大值翻倍,如t ...
- Python Tutorial 学习(六)--Modules
6. Modules 当你退出Python的shell模式然后又重新进入的时候,之前定义的变量,函数等都会没有了. 因此, 推荐的做法是将这些东西写入文件,并在适当的时候调用获取他们. 这就是为人所知 ...
- 使用C语言获取当前系统的时间
要想使用C语言来获取当前系统的时间,办法如下: 需要提前准备的工作: #include <stdio.h> #include <time.h> #include <std ...
- 利用TraceSource写日志
利用TraceSource写日志 从微软推出第一个版本的.NET Framework的时候,就在“System.Diagnostics”命名空间中提供了Debug和Trace两个类帮助我们完成针对调试 ...
- Web工程软件升级之数据库升级(一)
1. 首先检查oracle数据库版本是否正确 (可以使用方法 lsinventory来实现) 2. 检查oracle连接是否成功 3. 解压升级包,放到特定目录 4. 做升级前数据备份,备份主要业务数 ...
- Hadoop环境搭建-入门伪分布式配置(Mac OS,0.21.0,Eclipse 3.6)
http://www.linuxidc.com/Linux/2012-10/71900p2.htm http://andy-ghg.iteye.com/blog/1165453 为Mac的MyEcli ...
- vijos1082丛林探险
P1082丛林探险 描述 东非大裂谷中有一片神秘的丛林,是全世界探险家的乐园,著名黄皮肤探险家BB一直想去试试.正好我国科学家2005年4月将首次对东非大裂谷进行科考,BB决定随科考队去神秘丛林探险. ...
- 如何在不影响数据库的正常使用的情况下得到数据的完整.mdf和.ldf文
一:完整备份数据库 二:还原数据库 四:分离数据库即可得到.mdf和.ldf文件
- IIS的安装与配置
IIS的安装与配置 5.1.1. IIS安装视频教程 5.1.2. IIS配置与建站设置视频教程 IIS是什么 IIS是Internet Information Services(Internet信息 ...