IPBandwidth.Mod 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. MODULE IPBandwidth; (** AUTHOR "negelef"; PURPOSE "Bandwidth measurement on IP networks."; *)
  2. IMPORT Commands, Diagnostics, Kernel, Options, Streams, DNS, IP, TCP, UDP;
  3. CONST DefaultPort = 5772;
  4. CONST DefaultDuration = 10;
  5. TYPE Link = OBJECT
  6. VAR context: Commands.Context;
  7. VAR diagnostics: Diagnostics.StreamDiagnostics;
  8. VAR hostname: DNS.Name;
  9. VAR port, result: WORD;
  10. VAR address: IP.Adr;
  11. VAR buffer: ARRAY 65000 OF CHAR;
  12. PROCEDURE &Initialize (context: Commands.Context);
  13. BEGIN
  14. SELF.context := context;
  15. NEW (diagnostics, context.error);
  16. END Initialize;
  17. PROCEDURE Send;
  18. VAR sent: SIZE;
  19. BEGIN
  20. IF ~context.arg.GetString (hostname) THEN
  21. context.result := Commands.CommandParseError; RETURN;
  22. END;
  23. DNS.HostByName (hostname, address, result);
  24. IF result # DNS.Ok THEN
  25. diagnostics.Error (hostname, port, "failed to resolve");
  26. context.result := Commands.CommandError; RETURN;
  27. END;
  28. IF ~context.arg.GetInteger (port, FALSE) THEN
  29. port := DefaultPort;
  30. END;
  31. Connect;
  32. IF result # Streams.Ok THEN
  33. diagnostics.Error (hostname, port, "failed to connect to server");
  34. context.result := Commands.CommandError; RETURN;
  35. END;
  36. sent := 0;
  37. context.out.String ("Sending data..."); context.out.Ln; context.out.Update;
  38. WHILE ReceiveBytes () = 0 DO
  39. INC (sent, SendBytes ());
  40. IF result # Streams.Ok THEN
  41. Close;
  42. diagnostics.Error (hostname, port, "failed to send");
  43. context.result := Commands.CommandError; RETURN;
  44. END;
  45. END;
  46. Close;
  47. context.out.String ("Sent "); context.out.Size (sent); context.out.String (" bytes"); context.out.Ln; context.out.Update;
  48. END Send;
  49. PROCEDURE Receive;
  50. VAR duration, ticks: WORD; received: SIZE;
  51. BEGIN
  52. hostname := "server";
  53. IF ~context.arg.GetInteger (duration, FALSE) THEN
  54. duration := DefaultDuration;
  55. END;
  56. IF ~context.arg.GetInteger (port, FALSE) THEN
  57. port := DefaultPort;
  58. END;
  59. Listen;
  60. IF result # Streams.Ok THEN
  61. diagnostics.Error (hostname, port, "failed to connect to client");
  62. context.result := Commands.CommandError; RETURN;
  63. END;
  64. received := 0; ticks := 0;
  65. context.out.String ("Receiving data..."); context.out.Ln; context.out.Update;
  66. LOOP
  67. INC (received, ReceiveBytes ());
  68. IF result # Streams.Ok THEN
  69. Close;
  70. diagnostics.Error (hostname, port, "failed to receive");
  71. context.result := Commands.CommandError; RETURN;
  72. END;
  73. IF ticks = 0 THEN
  74. IF received # 0 THEN ticks := Kernel.GetTicks () + Kernel.second * duration END;
  75. ELSE
  76. IF Kernel.GetTicks () - ticks >= 0 THEN EXIT END;
  77. END;
  78. END;
  79. Close;
  80. context.out.String ("Received "); context.out.Size (received); context.out.String (" bytes in ");
  81. context.out.Int (duration, 0); context.out.String (" seconds"); context.out.Ln;
  82. context.out.String ("Bandwidth: "); context.out.FloatFix (received / (1000000 * duration), 0, 3, 0);
  83. context.out.String (" MB/s"); context.out.Ln; context.out.Update;
  84. END Receive;
  85. PROCEDURE Connect;
  86. BEGIN HALT (1001);
  87. END Connect;
  88. PROCEDURE Listen;
  89. BEGIN HALT (1001);
  90. END Listen;
  91. PROCEDURE SendBytes (): Streams.StreamSize;
  92. BEGIN HALT (1001);
  93. END SendBytes;
  94. PROCEDURE ReceiveBytes (): Streams.StreamSize;
  95. BEGIN HALT (1001);
  96. END ReceiveBytes;
  97. PROCEDURE Close;
  98. BEGIN HALT (1001);
  99. END Close;
  100. END Link;
  101. TYPE TCPLink = OBJECT (Link)
  102. VAR service, connection: TCP.Connection;
  103. PROCEDURE Connect;
  104. BEGIN
  105. NEW (connection);
  106. connection.Open (TCP.NilPort, address, port, result);
  107. END Connect;
  108. PROCEDURE Listen;
  109. BEGIN
  110. NEW (service);
  111. service.Open (port, IP.NilAdr, TCP.NilPort, result);
  112. IF result = TCP.Ok THEN
  113. context.out.String ("Waiting for client..."); context.out.Ln; context.out.Update;
  114. service.Accept (connection, result);
  115. END;
  116. END Listen;
  117. PROCEDURE SendBytes (): Streams.StreamSize;
  118. BEGIN
  119. connection.Send (buffer, 0, LEN (buffer), FALSE, result);
  120. RETURN LEN (buffer);
  121. END SendBytes;
  122. PROCEDURE ReceiveBytes (): Streams.StreamSize;
  123. VAR received: WORD;
  124. BEGIN
  125. IF connection.Available () # 0 THEN
  126. connection.Receive (buffer, 0, LEN (buffer), 1, received, result);
  127. IF result = TCP.Ok THEN RETURN received END;
  128. END;
  129. RETURN 0;
  130. END ReceiveBytes;
  131. PROCEDURE Close;
  132. BEGIN
  133. connection.Close;
  134. IF service # NIL THEN service.Close END;
  135. END Close;
  136. END TCPLink;
  137. TYPE UDPLink = OBJECT (Link)
  138. VAR socket: UDP.Socket;
  139. PROCEDURE Connect;
  140. BEGIN
  141. NEW (socket, UDP.NilPort, result);
  142. END Connect;
  143. PROCEDURE Listen;
  144. BEGIN
  145. NEW (socket, port, result);
  146. END Listen;
  147. PROCEDURE SendBytes (): Streams.StreamSize;
  148. BEGIN
  149. socket.Send (address, port, buffer, 0, LEN (buffer), result);
  150. RETURN LEN (buffer);
  151. END SendBytes;
  152. PROCEDURE ReceiveBytes (): Streams.StreamSize;
  153. VAR address: IP.Adr; port, received: WORD;
  154. BEGIN
  155. socket.Receive (buffer, 0, LEN (buffer), 0, address, port, received, result);
  156. IF result = UDP.Ok THEN RETURN received END;
  157. IF result = UDP.Timeout THEN result := UDP.Ok END;
  158. RETURN 0;
  159. END ReceiveBytes;
  160. PROCEDURE Close;
  161. BEGIN socket.Close;
  162. END Close;
  163. END UDPLink;
  164. (** Synposis: hostname [port] *)
  165. PROCEDURE SendTCP* (context: Commands.Context);
  166. VAR link: TCPLink;
  167. BEGIN
  168. NEW (link, context);
  169. link.Send;
  170. END SendTCP;
  171. (** Synposis: [duration] [port] *)
  172. PROCEDURE ReceiveTCP* (context: Commands.Context);
  173. VAR link: TCPLink; client: TCP.Connection;
  174. BEGIN
  175. NEW (link, context);
  176. link.Receive;
  177. END ReceiveTCP;
  178. (** Synposis: hostname [port] *)
  179. PROCEDURE SendUDP* (context: Commands.Context);
  180. VAR link: UDPLink;
  181. BEGIN
  182. NEW (link, context);
  183. link.Send;
  184. END SendUDP;
  185. (** Synposis: [duration] [port] *)
  186. PROCEDURE ReceiveUDP* (context: Commands.Context);
  187. VAR link: UDPLink;
  188. BEGIN
  189. NEW (link, context);
  190. link.Receive;
  191. END ReceiveUDP;
  192. END IPBandwidth.