| #!/usr/bin/python |
| # Copyright 2015 Google Inc. All Rights Reserved. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # |
| """UDP test client. |
| |
| This implements the client side of the UDP connection testing tool to evaluate |
| the effective speed of a link using bursts of UDP traffic. |
| """ |
| import select |
| import socket |
| import struct |
| import sys |
| import time |
| |
| import options |
| |
| optspec = """ |
| udp_test_client.py [options...] host_ip |
| -- |
| i,interval= Specify the cycle interval in seconds [2.0] |
| t,time= Specify the test length in seconds; zero means unlimited. [0] |
| """ |
| |
| try: |
| import monotime |
| except ImportError: |
| pass |
| try: |
| monotime = time.monotime |
| except AttributeError: |
| monotime = time.time |
| |
| |
| def parse_address(raw_address): |
| port = 5001 |
| |
| raw_host_addr = raw_address.split(':') |
| if len(raw_host_addr) > 1: |
| port = int(raw_host_addr[1]) |
| |
| return (raw_host_addr[0], port) |
| |
| |
| def main(): |
| o = options.Options(optspec) |
| opt, _, extra = o.parse(sys.argv[1:]) |
| |
| interval_length = float(opt.interval) |
| |
| host_addr = parse_address(extra[0]) |
| sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) |
| |
| packet_counter = 0 |
| packets_sent = 0 |
| packets_recv = 0 |
| respond_time = monotime() |
| start_time = monotime() |
| server_count = 0 |
| last_heard = monotime() |
| |
| print 'Host Address: %s' % host_addr[0] |
| |
| while True: |
| wait_time = interval_length - (monotime() - respond_time) |
| if wait_time < 0: |
| wait_time = 0 |
| sock_ready, _, _ = select.select([sock], [], [], wait_time) |
| if sock_ready: |
| data = sock.recv(65536) |
| magic, pack_type = struct.unpack('!4s4s', data[0:8]) |
| |
| if magic != 'TPDO': |
| continue |
| |
| if pack_type == 'RNNG': |
| packet_counter += 1 |
| _, _, server_count = struct.unpack('!4s4si', data[0:12]) |
| last_heard = monotime() |
| if monotime() - respond_time > interval_length: |
| temp_time = monotime() |
| counter_msg = struct.pack('!4s4siid', 'TPDO', 'UPDT', server_count, |
| packet_counter, temp_time) |
| sock.sendto(counter_msg, host_addr) |
| |
| if packet_counter > 0: |
| cycle_time = temp_time - respond_time |
| send_rate = server_count - packets_sent |
| recv_rate = packet_counter - packets_recv |
| if send_rate == 0: |
| success_rate = 0 |
| else: |
| success_rate = float(recv_rate) / send_rate |
| |
| print ('Send Rate: %.2fMbps, Receive Rate: %.2fMbps, ' |
| 'Success Rate: %.2f%%' % |
| (send_rate * len(data) * 8 / 1000000 / cycle_time, |
| recv_rate * len(data) * 8 / 1000000 / cycle_time, |
| success_rate * 100)) |
| |
| packets_sent = server_count |
| packets_recv = packet_counter |
| respond_time = monotime() |
| if monotime() - start_time > float(opt.time) and opt.time: |
| break |
| |
| if monotime() - last_heard > interval_length * 4: |
| sys.stderr.write('Failed, Connection Timed out') |
| sys.exit(1) |
| |
| if __name__ == '__main__': |
| main() |