socktest.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /*++
  2. Copyright (c) 2013 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. socktest.c
  9. Abstract:
  10. This module implements an application that tests out the system's socket
  11. functionality.
  12. Author:
  13. Evan Green 6-May-2013
  14. Environment:
  15. User Mode
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include <minoca/lib/types.h>
  21. #include <arpa/inet.h>
  22. #include <errno.h>
  23. #include <netinet/in.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <sys/socket.h>
  27. #include <unistd.h>
  28. //
  29. // ---------------------------------------------------------------- Definitions
  30. //
  31. //
  32. // ------------------------------------------------------ Data Type Definitions
  33. //
  34. //
  35. // ----------------------------------------------- Internal Function Prototypes
  36. //
  37. ULONG
  38. TestTransmitThroughput (
  39. ULONG ChunkSize,
  40. ULONG ChunkCount
  41. );
  42. //
  43. // -------------------------------------------------------------------- Globals
  44. //
  45. //
  46. // ------------------------------------------------------------------ Functions
  47. //
  48. int
  49. main (
  50. int ArgumentCount,
  51. char **Arguments
  52. )
  53. /*++
  54. Routine Description:
  55. This routine implements the socket test program.
  56. Arguments:
  57. ArgumentCount - Supplies the number of elements in the arguments array.
  58. Arguments - Supplies an array of strings. The array count is bounded by the
  59. previous parameter, and the strings are null-terminated.
  60. Return Value:
  61. 0 on success.
  62. Non-zero on failure.
  63. --*/
  64. {
  65. return TestTransmitThroughput(64 * 1024, 16);
  66. }
  67. //
  68. // --------------------------------------------------------- Internal Functions
  69. //
  70. ULONG
  71. TestTransmitThroughput (
  72. ULONG ChunkSize,
  73. ULONG ChunkCount
  74. )
  75. /*++
  76. Routine Description:
  77. This routine tests transmitting a large amount of data out of a socket.
  78. Arguments:
  79. ChunkSize - Supplies the size of each buffer passed to the send() function.
  80. ChunkCount - Supplies the number of chunks that will be sent.
  81. Return Value:
  82. Returns the number of failures that occurred in the test.
  83. --*/
  84. {
  85. ULONG ByteIndex;
  86. int BytesSent;
  87. struct sockaddr_in DestinationHost;
  88. ULONG Errors;
  89. ULONG LoopIndex;
  90. int Result;
  91. PCHAR TestSendBuffer;
  92. int TestSocket;
  93. Errors = 0;
  94. TestSendBuffer = NULL;
  95. TestSocket = socket(AF_INET, SOCK_STREAM, 0);
  96. if (TestSocket == -1) {
  97. printf("socket() failed. Errno = %d.\n", errno);
  98. Errors += 1;
  99. goto TestTransmitThroughputEnd;
  100. }
  101. //
  102. // TODO: Replace this with a real function (and not just a hard-coded
  103. // network order IP address.
  104. //
  105. DestinationHost.sin_family = AF_INET;
  106. DestinationHost.sin_port = htons(7653);
  107. DestinationHost.sin_addr.s_addr = (192 << 0) | (168 << 8) | (1 << 16) |
  108. (19 << 24);
  109. //
  110. // Connect to the remote host.
  111. //
  112. printf("Connecting to host...");
  113. Result = connect(TestSocket,
  114. (struct sockaddr *)&DestinationHost,
  115. sizeof(struct sockaddr_in));
  116. if (Result == 0) {
  117. printf("Connected.\n");
  118. } else {
  119. printf("Failed: Return value %d, errno = %d.\n", Result, errno);
  120. Errors += 1;
  121. goto TestTransmitThroughputEnd;
  122. }
  123. //
  124. // Allocate and initialize a big old test buffer.
  125. //
  126. TestSendBuffer = malloc(ChunkSize);
  127. if (TestSendBuffer == NULL) {
  128. printf("Failed to allocate %d bytes.\n", ChunkSize);
  129. Errors += 1;
  130. goto TestTransmitThroughputEnd;
  131. }
  132. for (ByteIndex = 0; ByteIndex < ChunkSize; ByteIndex += 1) {
  133. if ((ByteIndex & 0x1) == 0) {
  134. TestSendBuffer[ByteIndex] = (UCHAR)ByteIndex;
  135. } else {
  136. TestSendBuffer[ByteIndex] = (UCHAR)(ByteIndex >> 8);
  137. }
  138. }
  139. //
  140. // Loop sending data hardcore.
  141. //
  142. for (LoopIndex = 0; LoopIndex < ChunkCount; LoopIndex += 1) {
  143. BytesSent = send(TestSocket, TestSendBuffer, ChunkSize, 0);
  144. if (BytesSent == -1) {
  145. printf("Error: Failed to send chunk. errno = %d.\n", errno);
  146. Errors += 1;
  147. }
  148. if (BytesSent != ChunkSize) {
  149. printf("Error: send() sent only %d of %d bytes.\n",
  150. BytesSent,
  151. ChunkSize);
  152. Errors += 1;
  153. }
  154. //
  155. // At some point stop just stupidly printing out failures and give
  156. // up.
  157. //
  158. if (Errors > 10) {
  159. goto TestTransmitThroughputEnd;
  160. }
  161. }
  162. TestTransmitThroughputEnd:
  163. if (TestSendBuffer != NULL) {
  164. free(TestSendBuffer);
  165. }
  166. close(TestSocket);
  167. printf("TestTransmitThroughput done. %d errors found.\n", Errors);
  168. return Errors;
  169. }