├── README ├── c-stun-client-api.c ├── c-stun-client-demo.c ├── py-stun-client-demo.py ├── py-tcp-echo-client.py ├── py-tcp-echo-server.py ├── py-udp-echo-client.py ├── py-udp-echo-server-class.py ├── py-udp-echo-server.py └── py-udp-ping.py /README: -------------------------------------------------------------------------------- 1 | WHAT IS THIS ? 2 | 3 | turn-client is the utility tool for TURN client demo and TURN client API with python and C . TURN is defined by RFC5766 http://www.ietf.org/rfc/rfc5766.txt , and also with STUN - RFC5389 http://www.ietf.org/rfc/rfc5389.txt . 4 | 5 | 6 | TODO: 7 | - py-turn-client-api.py 8 | - py-turn-client-demo.py 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /c-stun-client-api.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | /* 9 | * 10 | * STUN(RFC5389) client api by Chris 11 | * 12 | * Test by turnserver-0.6 from http://turnserver.sourceforge.net 13 | * 14 | * @ 2012-2-28 Shenszhen, China 15 | * @ 2012-2-29 version 0.1 16 | */ 17 | 18 | 19 | int stun_xor_addr(int sockfd,char * stun_server_ip,unsigned short stun_server_port, char * return_ip, unsigned short * return_port); 20 | 21 | 22 | 23 | int main(int argc, char *argv[]) 24 | { 25 | if (argc != 4) { 26 | printf("STUN(RFC5389) client api by Chris \n"); 27 | printf("usage: %s \n\n", argv[0]); 28 | exit(1); 29 | } 30 | 31 | 32 | printf("Main start ... \n"); 33 | 34 | struct sockaddr_in localaddr; 35 | int n; 36 | 37 | int sockfd; 38 | char return_ip[32]; 39 | unsigned short return_port=0; 40 | 41 | //# create socket 42 | sockfd = socket(AF_INET, SOCK_DGRAM, 0); // UDP 43 | 44 | 45 | // local 46 | bzero(&localaddr, sizeof(localaddr)); 47 | localaddr.sin_family = AF_INET; 48 | localaddr.sin_port = htons(atoi(argv[3])); 49 | 50 | n = bind(sockfd,(struct sockaddr *)&localaddr,sizeof(localaddr)); 51 | //printf("bind result=%d\n",n); 52 | 53 | printf("socket opened to %s:%s at local port %s\n",argv[1],argv[2],argv[3]); 54 | 55 | 56 | n = stun_xor_addr(sockfd,argv[1],(unsigned short)atoi(argv[2]),return_ip,&return_port); 57 | if (n!=0) 58 | printf("STUN req error : %d\n",n); 59 | else 60 | printf("ip:port = %s:%d\n",return_ip,return_port); 61 | 62 | printf("main over.\n"); 63 | 64 | } 65 | 66 | int stun_xor_addr(int sockfd,char * stun_server_ip,unsigned short stun_server_port,char * return_ip, unsigned short * return_port) 67 | { 68 | struct sockaddr_in servaddr; 69 | unsigned char buf[300]; 70 | int i; 71 | unsigned char bindingReq[20]; 72 | 73 | int stun_method,msg_length; 74 | short attr_type; 75 | short attr_length; 76 | short port; 77 | short n; 78 | 79 | // server 80 | bzero(&servaddr, sizeof(servaddr)); 81 | servaddr.sin_family = AF_INET; 82 | inet_pton(AF_INET, stun_server_ip, &servaddr.sin_addr); 83 | servaddr.sin_port = htons(stun_server_port); 84 | 85 | 86 | //## first bind 87 | * (short *)(&bindingReq[0]) = htons(0x0001); // stun_method 88 | * (short *)(&bindingReq[2]) = htons(0x0000); // msg_length 89 | * (int *)(&bindingReq[4]) = htonl(0x2112A442);// magic cookie 90 | 91 | *(int *)(&bindingReq[8]) = htonl(0x63c7117e); // transacation ID 92 | *(int *)(&bindingReq[12])= htonl(0x0714278f); 93 | *(int *)(&bindingReq[16])= htonl(0x5ded3221); 94 | 95 | 96 | 97 | //printf("Send data ...\n"); 98 | n = sendto(sockfd, bindingReq, sizeof(bindingReq),0,(struct sockaddr *)&servaddr, sizeof(servaddr)); // send UDP 99 | if (n == -1) 100 | { 101 | printf("sendto error\n"); 102 | return -1; 103 | } 104 | // time wait 105 | usleep(1000 * 100); 106 | 107 | //printf("Read recv ...\n"); 108 | n = recvfrom(sockfd, buf, 300, 0, NULL,0); // recv UDP 109 | if (n == -1) 110 | { 111 | printf("recvfrom error\n"); 112 | return -2; 113 | } 114 | //printf("Response from server:\n"); 115 | //write(STDOUT_FILENO, buf, n); 116 | 117 | if (*(short *)(&buf[0]) == htons(0x0101)) 118 | { 119 | //printf("STUN binding resp: success !\n"); 120 | 121 | // parse XOR 122 | n = htons(*(short *)(&buf[2])); 123 | i = 20; 124 | while(i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define MAXLINE 200 9 | 10 | /* 11 | * 12 | * STUN(RFC5389) client demo by Chris 13 | * 14 | * Test by turnserver-0.6 from http://turnserver.sourceforge.net 15 | * 16 | * @ 2012-2-27 AT Shenzhen, China 17 | * @ 2012-2-29 version 0.1 18 | */ 19 | 20 | int stun_xor_addr(char * stun_server_ip,short stun_server_port,short local_port,char * return_ip_port); 21 | 22 | 23 | int main(int argc, char *argv[]) 24 | { 25 | if (argc != 4) { 26 | printf("STUN(RFC5389) client demo by Chris \n"); 27 | printf("usage: %s \n\n", argv[0]); 28 | exit(1); 29 | } 30 | 31 | 32 | printf("Main start ... \n"); 33 | 34 | int n = 0; 35 | char return_ip_port[50]; 36 | n = stun_xor_addr(argv[1],atoi(argv[2]),atoi(argv[3]),return_ip_port); 37 | if (n!=0) 38 | printf("STUN req error : %d\n",n); 39 | else 40 | printf("ip:port = %s\n",return_ip_port); 41 | 42 | printf("Main over.\n"); 43 | 44 | } 45 | 46 | int stun_xor_addr(char * stun_server_ip,short stun_server_port,short local_port,char * return_ip_port) 47 | { 48 | struct sockaddr_in servaddr; 49 | struct sockaddr_in localaddr; 50 | unsigned char buf[MAXLINE]; 51 | int sockfd, i; 52 | unsigned char bindingReq[20]; 53 | 54 | int stun_method,msg_length; 55 | short attr_type; 56 | short attr_length; 57 | short port; 58 | short n; 59 | 60 | 61 | //# create socket 62 | sockfd = socket(AF_INET, SOCK_DGRAM, 0); // UDP 63 | 64 | // server 65 | bzero(&servaddr, sizeof(servaddr)); 66 | servaddr.sin_family = AF_INET; 67 | inet_pton(AF_INET, stun_server_ip, &servaddr.sin_addr); 68 | servaddr.sin_port = htons(stun_server_port); 69 | 70 | // local 71 | bzero(&localaddr, sizeof(localaddr)); 72 | localaddr.sin_family = AF_INET; 73 | //inet_pton(AF_INET, "192.168.0.181", &localaddr.sin_addr); 74 | localaddr.sin_port = htons(local_port); 75 | 76 | n = bind(sockfd,(struct sockaddr *)&localaddr,sizeof(localaddr)); 77 | //printf("bind result=%d\n",n); 78 | 79 | printf("socket opened to %s:%d at local port %d\n",stun_server_ip,stun_server_port,local_port); 80 | 81 | //## first bind 82 | * (short *)(&bindingReq[0]) = htons(0x0001); // stun_method 83 | * (short *)(&bindingReq[2]) = htons(0x0000); // msg_length 84 | * (int *)(&bindingReq[4]) = htonl(0x2112A442);// magic cookie 85 | 86 | *(int *)(&bindingReq[8]) = htonl(0x63c7117e); // transacation ID 87 | *(int *)(&bindingReq[12])= htonl(0x0714278f); 88 | *(int *)(&bindingReq[16])= htonl(0x5ded3221); 89 | 90 | 91 | 92 | printf("Send data ...\n"); 93 | n = sendto(sockfd, bindingReq, sizeof(bindingReq),0,(struct sockaddr *)&servaddr, sizeof(servaddr)); // send UDP 94 | if (n == -1) 95 | { 96 | printf("sendto error\n"); 97 | return -1; 98 | } 99 | 100 | // time wait 101 | sleep(1); 102 | 103 | printf("Read recv ...\n"); 104 | n = recvfrom(sockfd, buf, MAXLINE, 0, NULL,0); // recv UDP 105 | if (n == -1) 106 | { 107 | printf("recvfrom error\n"); 108 | return -2; 109 | } 110 | //printf("Response from server:\n"); 111 | //write(STDOUT_FILENO, buf, n); 112 | 113 | if (*(short *)(&buf[0]) == htons(0x0101)) 114 | { 115 | printf("STUN binding resp: success !\n"); 116 | 117 | // parse XOR 118 | n = htons(*(short *)(&buf[2])); 119 | i = 20; 120 | while(i 5 | USAGE: 6 | \t%s [STUN_server_port | 3478] [ ] 7 | ''' 8 | 9 | # 10 | # 2012-2-25 AT Shenzhen, China 11 | # 2012-2-27 version 0.1 12 | # 13 | 14 | # TODO: 15 | # - send binging request again 16 | # 17 | 18 | ## parse CLI 19 | from sys import argv 20 | import sys 21 | 22 | if len(argv)!=2 and len(argv)!=3 and len(argv)!=5: 23 | print __doc__ % argv[0] 24 | sys.exit() 25 | 26 | # default configuration 27 | host = argv[1] #"192.168.0.181" 28 | port = 3478 29 | local_ip = '192.168.0.75' 30 | local_port = 7878 31 | if len(argv)==3: 32 | port = int(argv[2]) 33 | 34 | if len(argv)==5: 35 | local_ip = argv[3] 36 | local_port = int(argv[4]) 37 | 38 | ## STUN method & class & attribute 39 | STUN_MAGIC_COOKIE = 0x2112A442 40 | STUN_method={'STUN_METHOD_BINDING':0x0001} 41 | 42 | STUN_class={ 43 | 'STUN_REQUEST': 0x0000, 44 | 'STUN_SUCCESS_RESP':0x0100, 45 | 'STUN_ERROR_RESP': 0x0110, 46 | 'STUN_INDICATION': 0x0010 47 | } 48 | 49 | def IS_REQUEST(msg_class): return (((msg_class) & 0x0110) == 0x0000) 50 | def IS_SUCCESS_RESP(msg_class): return (((msg_class) & 0x0110) == 0x0100) 51 | def IS_ERR_RESP(msg_class): return (((msg_class) & 0x0110) == 0x0110) 52 | def IS_INDICATION(msg_class): return (((msg_class) & 0x0110) == 0x0010) 53 | def STUN_GET_METHOD(msg_type): return ((msg_type) & 0x3EEF) 54 | def STUN_GET_CLASS(msg_type): return ((msg_type) & 0x0110) 55 | def STUN_IS_COMPREHENSION_REQUIRED(attr_type): return (not((attr_type) & 0x8000)) 56 | def STUN_IS_COMPREHENSION_OPTIONAL(attr_type): return (((attr_type) & 0x8000)) 57 | 58 | STUN_ATTR_MAPPED_ADDRESS = 0x0001 59 | STUN_ATTR_USERNAME = 0x0006 60 | STUN_ATTR_MESSAGE_INTEGRITY = 0x0008 61 | STUN_ATTR_ERROR_CODE = 0x0009 62 | STUN_ATTR_UNKNOWN_ATTRIBUTES= 0x000A 63 | STUN_ATTR_REALM = 0x0014 64 | STUN_ATTR_NONCE = 0x0015 65 | STUN_ATTR_XOR_MAPPED_ADDRESS= 0x0020 66 | STUN_ATTR_SOFTWARE = 0x8022 67 | STUN_ATTR_ALTERNATE_SERVER = 0x8023 68 | STUN_ATTR_FINGERPRINT = 0x8028 69 | 70 | ## utility 71 | # generate transaction ID 72 | import random 73 | def genTranID(): 74 | a = ''.join([random.choice('0123456789ABCDEF') for x in xrange(32)]) 75 | return binascii.a2b_hex(a) 76 | #return a 77 | 78 | # parse received response packet 79 | def recv_resp(buf): 80 | msgType = int(binascii.b2a_hex(buf[0:2]),16) 81 | msgLength = int(binascii.b2a_hex(buf[2:4]),16) 82 | magic_cookie = binascii.b2a_hex(buf[4:8]) 83 | transId = binascii.b2a_hex(buf[8:20]) 84 | 85 | header = (msgType,msgLength,magic_cookie,transId) 86 | 87 | print '\n>>header: ' 88 | print hex(msgType),msgLength,magic_cookie,transId 89 | if IS_SUCCESS_RESP(msgType): 90 | pass #print 'Success resp' 91 | elif IS_ERR_RESP(msgType): 92 | print 'Error resp' 93 | else: 94 | print 'Unknown msg type' 95 | 96 | print '>>attrs:' 97 | attrs = [] 98 | len_remain = msgLength 99 | base = 20 100 | while len_remain>=4: 101 | attr_type = int(binascii.b2a_hex(buf[base:(base+2)]),16) 102 | attr_len = int(binascii.b2a_hex(buf[(base+2):(base+4)]),16) 103 | attr_value = binascii.b2a_hex(buf[base+4:base+4+attr_len]) 104 | 105 | if attr_type == STUN_ATTR_XOR_MAPPED_ADDRESS: # 0x0020 106 | port = 0x2112 ^ int(binascii.b2a_hex(buf[base+6:base+8]), 16) 107 | tip =[1,2,3,4] 108 | tip[0] = 0x21 ^ int(binascii.b2a_hex(buf[base+8:base+9]), 16) 109 | tip[1] = 0x12 ^ int(binascii.b2a_hex(buf[base+9:base+10]), 16) 110 | tip[2] = 0xA4 ^ int(binascii.b2a_hex(buf[base+10:base+11]), 16) 111 | tip[3] = 0x42 ^ int(binascii.b2a_hex(buf[base+11:base+12]), 16) 112 | ip = '.'.join([str(x) for x in tip]) 113 | 114 | attrs.append([attr_type,ip+':'+str(port)]) 115 | print attr_type, ip,':',port,' (XOR=',attr_value,')' 116 | else: 117 | attrs.append([attr_type,attr_value]) 118 | print attr_type,str(int(attr_value,16)) 119 | 120 | base = base + 4 + attr_len 121 | len_remain = len_remain - (4+attr_len) 122 | 123 | #print 'body: ',attrs 124 | 125 | return (header,attrs) 126 | 127 | ## connect STUN server 128 | import socket 129 | import struct 130 | import binascii 131 | 132 | 133 | ## first bind 134 | def stun_binding_first(sock): 135 | print '\nSTUN binding request ...' 136 | # header 137 | header = struct.pack('!H',STUN_method['STUN_METHOD_BINDING']) # binding req 138 | header += struct.pack('!H',0x0000) # length 139 | header += struct.pack('!l',STUN_MAGIC_COOKIE) # magic cookie 140 | header += struct.pack('!32s',genTranID()) # trans ID 141 | # body 142 | body = struct.pack('!H',0x8022) # software 143 | body += struct.pack('!h',0x0014) # length 144 | body += struct.pack('!20s','PY STUN CLIENT 0.1')#value 145 | # msg 146 | send_data = header #+ body # TODO 147 | 148 | 149 | print 'Send data ...' 150 | r = sock.sendto(send_data,(host,port)) 151 | print 'size=',r 152 | 153 | print 'Recv data ...' 154 | buf,address = sock.recvfrom(1024) 155 | print 'size=',len(buf) 156 | 157 | print 'data: ',buf 158 | print 'from: ',address 159 | 160 | (header,attr) = recv_resp(buf) 161 | 162 | # TODD: parse: realm, nonce 163 | print '' 164 | return (header,attr) 165 | 166 | ## bind again 167 | def stun_binding_again(sock): 168 | pass 169 | # TODO: parse: xor-mapped-address 170 | 171 | 172 | if __name__ == '__main__': 173 | print 'STUN(RFC5389) client demo by Chris \n' 174 | 175 | print 'Connect to server : ',host,port 176 | sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) 177 | print 'Bind local ip:port : ',local_ip,local_port 178 | sock.bind((local_ip,local_port)) 179 | 180 | # binding first 181 | msg = stun_binding_first(sock) 182 | 183 | 184 | got_XOR_MAPPED_ADDR = False 185 | XOR_MAPPED_ADDR = None 186 | for x in msg[1]: 187 | if x[0]== STUN_ATTR_XOR_MAPPED_ADDRESS: 188 | got_XOR_MAPPED_ADDR = True 189 | XOR_MAPPED_ADDR = x[1] 190 | break; 191 | 192 | if got_XOR_MAPPED_ADDR: 193 | print '>>> Success! XOR-MAPPED-ADDRESS=',XOR_MAPPED_ADDR 194 | else: 195 | print '>>> First binding error ,and try again ...' 196 | pass 197 | # TODO: msg = stun_binding_again(sock) 198 | 199 | print 'END!' 200 | 201 | #END -------------------------------------------------------------------------------- /py-tcp-echo-client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | ''' 3 | python TCP echo client by Chris 4 | USAGE: %s 5 | ''' 6 | 7 | # 2012-2-22 Shenzhen, China 8 | 9 | import socket 10 | from sys import argv 11 | 12 | def f(host,port,msg): 13 | sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 14 | sock.connect((host,port)) 15 | 16 | sock.send(msg) 17 | print 'send data: ',msg 18 | recv_msg = sock.recv(100) 19 | print 'recv data: ',recv_msg 20 | 21 | 22 | sock.close() 23 | 24 | 25 | 26 | 27 | 28 | print '>>start' 29 | 30 | if __name__ == '__main__': 31 | if len(argv)!=4: 32 | print __doc__ % argv[0] 33 | else: 34 | f(argv[1],int(argv[2]),argv[3]) 35 | 36 | print '>>END!' 37 | -------------------------------------------------------------------------------- /py-tcp-echo-server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | ''' 3 | python TCP echo sever by Chris 4 | USAGE: %s 5 | ''' 6 | 7 | # 2012-2-22 Shenzhen, China 8 | 9 | import socket 10 | from sys import argv 11 | 12 | 13 | def f(host,port): 14 | sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) 15 | sock.bind((host,port)) 16 | sock.listen(10) 17 | 18 | while True: 19 | conn,client = sock.accept() 20 | print '\nnew client: ',client 21 | data = conn.recv(1024) 22 | print 'recv data: ',data 23 | if data: 24 | conn.send(data) 25 | print 'resp data: ',data 26 | 27 | sock.close() 28 | 29 | 30 | 31 | print '>>start ' 32 | 33 | if __name__ == '__main__': 34 | if len(argv) != 3: 35 | print __doc__ % argv[0] 36 | else: 37 | f(argv[1],int(argv[2])) 38 | 39 | 40 | print '>>end!' 41 | -------------------------------------------------------------------------------- /py-udp-echo-client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | ''' 3 | python UDP echo client by Chris 4 | USAGE: %s 5 | ''' 6 | 7 | # 2012-2-22 Shenzhen, China 8 | 9 | import socket 10 | import time 11 | from sys import argv 12 | 13 | def f(host,port,msg): 14 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 15 | print 'connect to server: ',host,port 16 | 17 | print 'send msg: ',msg 18 | sock.sendto(msg,(host,port)) 19 | print 'recv msg: ',sock.recv(1024) 20 | 21 | sock.close() 22 | 23 | 24 | print '>>>Start ...' 25 | if __name__ == '__main__': 26 | if len(argv) !=4: 27 | print __doc__ % argv[0] 28 | else: 29 | f(argv[1],int(argv[2]),argv[3]) 30 | 31 | print '>>>END!' 32 | 33 | -------------------------------------------------------------------------------- /py-udp-echo-server-class.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | ''' 3 | python UDP echo server by Chris 4 | USAGE: %s 5 | ''' 6 | 7 | # 2012-2-22 Shenzhen, China 8 | # 9 | 10 | from SocketServer import DatagramRequestHandler, UDPServer 11 | from sys import argv 12 | 13 | class EchoHandler(DatagramRequestHandler): 14 | def handle(self): 15 | print "\nClient connected:", self.client_address 16 | message = self.rfile.read() 17 | print 'recv data: ',message 18 | self.wfile.write(message) 19 | print 'resp data: ',message 20 | 21 | print '>> start ' 22 | 23 | if __name__ == '__main__': 24 | if len(argv) != 3: 25 | print __doc__ % argv[0] 26 | else: 27 | UDPServer((argv[1],int(argv[2])), EchoHandler).serve_forever() 28 | 29 | print '< 4 | USAGE: %s 5 | ''' 6 | 7 | # 2012-2-22 Shenzhen, China 8 | # 9 | 10 | import socket 11 | from sys import argv 12 | 13 | def f(host,port): 14 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 15 | sock.bind((host, port)) 16 | 17 | while True: 18 | 19 | # receive 20 | data,client = sock.recvfrom(1024) 21 | if not data: 22 | print 'client has existed: ',client 23 | continue #break 24 | print '\nrecv data from ',client,': ',data 25 | 26 | # response 27 | sock.sendto(data,client) 28 | print 'resp data to ',client,' : ',data 29 | 30 | sock.close() 31 | 32 | 33 | 34 | print '>>Start ...' 35 | 36 | if __name__ == '__main__': 37 | if len(argv) != 3: 38 | print __doc__ % argv[0] 39 | else: 40 | f(argv[1],int(argv[2])) 41 | 42 | print '>>END!' 43 | 44 | -------------------------------------------------------------------------------- /py-udp-ping.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | #-*- coding: UTF-8 -*- 3 | ''' 4 | python UDP ping tool by Chris 5 | USAGE: 6 | \t%s [ping_count] 7 | ''' 8 | 9 | # 2012-3-8 Shenzhen,China 10 | # 11 | 12 | from sys import argv 13 | import sys 14 | 15 | if len(argv) != 2 and len(argv) != 3: 16 | print __doc__ % argv[0] 17 | sys.exit() 18 | 19 | remote_host = ('192.168.123.128',9800) 20 | #local_host = ('192.168.123.128',9801) 21 | n = 5 22 | data_bytes = 32 23 | data = ''.join(['*' for x in range(data_bytes)]) 24 | 25 | remote_ip_port = argv[1].split(':') 26 | if len(remote_ip_port)!=2: 27 | print __doc__ % argv[0] 28 | sys.exit() 29 | remote_host = (remote_ip_port[0],int(remote_ip_port[1])) 30 | if len(argv) == 3: 31 | n = int(argv[2]) 32 | 33 | import socket 34 | import time 35 | socket.setdefaulttimeout(3) 36 | sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) 37 | #sock.bind(local_host) 38 | 39 | print '' 40 | print 'Ping ',remote_host,' with %d bytes of data:' % data_bytes 41 | print '' 42 | 43 | send_n = 0 44 | recv_n = 0 45 | lost_n = 0 46 | tt = [] 47 | 48 | for x in range(1,n+1): 49 | t0 = time.time() 50 | try: 51 | n = sock.sendto(data,remote_host) 52 | print 'Ping %d bytes=%d ; ' % (x,n) , 53 | send_n += 1 54 | 55 | t0 = time.time() 56 | d,addr = sock.recvfrom(1024) 57 | t1 = time.time()-t0 58 | print 'Reply from ',addr,' bytes=%d time=%dms ' % (len(d),t1) 59 | recv_n += 1 60 | tt.append(t1) 61 | except socket.error, msg: 62 | print 'Recvfrom except : ', msg, ' time=%dms ' % (time.time()-t0) 63 | lost_n += 1 64 | 65 | time.sleep(0.5) 66 | 67 | print '' 68 | print 'Ping statistics for ' ,remote_host,':' 69 | if send_n>0: 70 | print '\tPackes: Sent = %d, Received = %d, Lost = %d (%d%% loss) ,' % (send_n,recv_n,lost_n,lost_n*100/send_n) 71 | else: 72 | print 'None.' 73 | print 'Approximate round trip times in milli-seconds:' 74 | if tt: 75 | print '\tMinimum = %dms, Maximum = %dms, Average = %dms' % (min(tt),max(tt),sum(tt)/len(tt)) 76 | else: 77 | print '\tNone.' 78 | print '' 79 | 80 | # END --------------------------------------------------------------------------------