[4] | 1 | /****************************************************************************** |
---|
| 2 | * QUANTA - A toolkit for High Performance Data Sharing |
---|
| 3 | * Copyright (C) 2003 Electronic Visualization Laboratory, |
---|
| 4 | * University of Illinois at Chicago |
---|
| 5 | * |
---|
| 6 | * All rights reserved. |
---|
| 7 | * |
---|
| 8 | * Redistribution and use in source and binary forms, with or without |
---|
| 9 | * modification, are permitted provided that the following conditions are met: |
---|
| 10 | * |
---|
| 11 | * * Redistributions of source code must retain the above copyright |
---|
| 12 | * notice, this list of conditions and the following disclaimer. |
---|
| 13 | * * Redistributions in binary form must reproduce the above |
---|
| 14 | * copyright notice, this list of conditions and the following disclaimer |
---|
| 15 | * in the documentation and/or other materials provided with the distribution. |
---|
| 16 | * * Neither the name of the University of Illinois at Chicago nor |
---|
| 17 | * the names of its contributors may be used to endorse or promote |
---|
| 18 | * products derived from this software without specific prior written permission. |
---|
| 19 | * |
---|
| 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
---|
| 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
---|
| 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
---|
| 23 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
---|
| 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
---|
| 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
---|
| 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
---|
| 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
---|
| 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
---|
| 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
---|
| 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
---|
| 31 | * |
---|
| 32 | * Direct questions, comments etc about Quanta to cavern@evl.uic.edu |
---|
| 33 | *****************************************************************************/ |
---|
| 34 | |
---|
| 35 | /* |
---|
| 36 | This is a C++ class to support TCP/IP sockets. |
---|
| 37 | The 2 main classes are QUANTAnet_tcpClient_c and QUANTAnet_tcpServer_c. |
---|
| 38 | |
---|
| 39 | If you are writing a server you need to instantiate a tcpServer object. |
---|
| 40 | Likewise if you are writing a client you need to instantiate a tcpClient |
---|
| 41 | object. |
---|
| 42 | |
---|
| 43 | */ |
---|
| 44 | |
---|
| 45 | #ifndef _QUANTAPLUS_TCP_C |
---|
| 46 | #define _QUANTAPLUS_TCP_C |
---|
| 47 | |
---|
| 48 | #include "QUANTAnet_socketbase_c.hxx" |
---|
| 49 | #include "QUANTAnet_perfMonitor_c.hxx" |
---|
| 50 | #include "QUANTAnet_iovec_c.hxx" |
---|
| 51 | //#include <QUANTAnet_perfDaemon_c.hxx> |
---|
| 52 | |
---|
| 53 | class QUANTAnet_perfMonitor_c; |
---|
| 54 | class QUANTAnet_tcpServer_c; |
---|
| 55 | //class QUANTAnet_perfDaemon_c; |
---|
| 56 | |
---|
| 57 | /** TCP Class for creating client connections. This class bypasses QUANTA's standard method for establishing connections and provides the user with direct control of TCP connections. |
---|
| 58 | |
---|
| 59 | */ |
---|
| 60 | class QUANTAnet_tcpClient_c : public QUANTAnet_socketbase_c { |
---|
| 61 | |
---|
| 62 | // Allow QUANTAnet_tcpServer_c objects to call MakeNonBlocking. |
---|
| 63 | friend class QUANTAnet_tcpServer_c; |
---|
| 64 | |
---|
| 65 | protected: |
---|
| 66 | /* Not to be called by user */ |
---|
| 67 | void makeNonBlocking(); |
---|
| 68 | |
---|
| 69 | struct sockaddr_in clientInfo; |
---|
| 70 | int clientSockFd; |
---|
| 71 | int clientStatus; |
---|
| 72 | int timeOutStatus; |
---|
| 73 | int timeOutPeriod; |
---|
| 74 | QUANTAnet_perfMonitor_c pmonitor; |
---|
| 75 | public: |
---|
| 76 | |
---|
| 77 | /// Blocking parameter values for Read/Write method. |
---|
| 78 | //@{ |
---|
| 79 | /// Make the connection blocking but time out eventually. |
---|
| 80 | static const int BLOCKING/* = 1*/; |
---|
| 81 | |
---|
| 82 | /// Make the connection non blocking. |
---|
| 83 | static const int NON_BLOCKING/* = 2*/; |
---|
| 84 | |
---|
| 85 | // Make the conncection blocking and never time out. |
---|
| 86 | //static const int NEVER_TIME_OUT_BLOCKING/* = 3*/; |
---|
| 87 | |
---|
| 88 | //@} |
---|
| 89 | |
---|
| 90 | /// Time out values. |
---|
| 91 | //@{ |
---|
| 92 | /// Used to set time out period to never time out. |
---|
| 93 | static const int NO_TIME_OUT/* = -1*/; |
---|
| 94 | |
---|
| 95 | /// Default time out is no time out. |
---|
| 96 | static const int DEFAULT_TIME_OUT/* = NO_TIME_OUT*/; |
---|
| 97 | //@} |
---|
| 98 | |
---|
| 99 | /// Return values from Read/Write methods. |
---|
| 100 | //@{ |
---|
| 101 | /// Socket is not open. |
---|
| 102 | static const int SOCKET_NOT_OPEN/* = -1*/; |
---|
| 103 | |
---|
| 104 | /// Connection you attempted to read/write is terminated. |
---|
| 105 | static const int CONNECTION_TERMINATED/* = -2*/; |
---|
| 106 | |
---|
| 107 | /// You attempted to read with non blocking and there was not data. |
---|
| 108 | static const int NON_BLOCKING_HAS_NO_DATA/* = -3*/; |
---|
| 109 | |
---|
| 110 | /// The read/write timed out. |
---|
| 111 | static const int TIMED_OUT/* = -4*/; |
---|
| 112 | |
---|
| 113 | /// Read/Write succeeded. |
---|
| 114 | static const int OK/* = 1*/; |
---|
| 115 | |
---|
| 116 | /// You attempted to write with non blocking and socket was not ready. |
---|
| 117 | static const int NON_BLOCKING_NOT_READY_TO_WRITE/* = -6*/; |
---|
| 118 | |
---|
| 119 | /// Socket was not ready. |
---|
| 120 | static const int NOT_READY/* = -7*/; |
---|
| 121 | |
---|
| 122 | /// Socket ready to read. |
---|
| 123 | static const int READY_TO_READ/* = -8*/; |
---|
| 124 | |
---|
| 125 | /// Socket ready to write. |
---|
| 126 | static const int READY_TO_WRITE/* = -9*/; |
---|
| 127 | |
---|
| 128 | /// Socket ready to read and write. |
---|
| 129 | static const int READY_TO_READ_AND_WRITE/* = -10*/; |
---|
| 130 | |
---|
| 131 | /// Change the socket buffer size before Read(). |
---|
| 132 | static const int READ_BUFFER_SIZE/* = -11*/; |
---|
| 133 | |
---|
| 134 | /// Change the socket buffer size before Write(). |
---|
| 135 | static const int WRITE_BUFFER_SIZE/* = -12*/; |
---|
| 136 | //@} |
---|
| 137 | |
---|
| 138 | |
---|
| 139 | /** Set timeout period when performing read() or write() operations. |
---|
| 140 | @param t Time out period in seconds. Set to QUANTAnet_tcpClient_c::NO_TIME_OUT to set no time out period. |
---|
| 141 | */ |
---|
| 142 | void setTimeOut(int t) {timeOutPeriod = t;} |
---|
| 143 | |
---|
| 144 | /// Get timeout period |
---|
| 145 | int getTimeOut() {return timeOutPeriod;} |
---|
| 146 | |
---|
| 147 | /** Set client info. For internal use. |
---|
| 148 | @param info client information |
---|
| 149 | */ |
---|
| 150 | void setClientInfo(struct sockaddr_in* info) { clientInfo = *info; } |
---|
| 151 | |
---|
| 152 | /** Set client socket. For internal use. |
---|
| 153 | @param sockfd client socket |
---|
| 154 | */ |
---|
| 155 | void setClientSockFd(int sockfd) { clientSockFd = sockfd; } |
---|
| 156 | |
---|
| 157 | QUANTAnet_tcpClient_c(); |
---|
| 158 | virtual ~QUANTAnet_tcpClient_c() { if (clientSockFd) close(); } |
---|
| 159 | |
---|
| 160 | /// Accessor functions |
---|
| 161 | //@{ |
---|
| 162 | /** Get the IP address of remote connection. |
---|
| 163 | If you are a client this returns the ip of the destination server. |
---|
| 164 | If you are a server this returns the ip of the destination client. |
---|
| 165 | */ |
---|
| 166 | unsigned int getRemoteIP(); |
---|
| 167 | |
---|
| 168 | /** Get the IP address of remote connection. |
---|
| 169 | If you are a client this returns the ip of the destination server. |
---|
| 170 | If you are a server this returns the ip of the destination client. |
---|
| 171 | */ |
---|
| 172 | void getRemoteIP(char* name); |
---|
| 173 | |
---|
| 174 | /// Get port of self. |
---|
| 175 | int getSelfPort(); |
---|
| 176 | |
---|
| 177 | /// Get port of client. |
---|
| 178 | int getRemotePort(); |
---|
| 179 | |
---|
| 180 | /// Get socket id |
---|
| 181 | int getSocketId(); |
---|
| 182 | //@} |
---|
| 183 | |
---|
| 184 | /**@name Read and Write calls.*/ |
---|
| 185 | //@{ |
---|
| 186 | /** |
---|
| 187 | @param nbytes |
---|
| 188 | |
---|
| 189 | Fill nbytes with num bytes you want to read. |
---|
| 190 | nbytes will return with number of bytes successfully read. |
---|
| 191 | |
---|
| 192 | @param blockingtype |
---|
| 193 | |
---|
| 194 | BLOCKING means that it will block waiting for data or until |
---|
| 195 | the timeout period expires. Change the timeout period by |
---|
| 196 | calling setTimeOut(). |
---|
| 197 | |
---|
| 198 | NON_BLOCKING means that if there is no data to be read this call will |
---|
| 199 | return immediately. If it does get some data it will keep reading |
---|
| 200 | until the specified number of bytes is received, or if it timesout, or if |
---|
| 201 | the connection is broken. In the latter two cases the number of bytes |
---|
| 202 | it was able to read is returned. |
---|
| 203 | |
---|
| 204 | In either the BLOCKING or NON_BLOCKING case you can set the |
---|
| 205 | time out period to never time out by setting the timeout |
---|
| 206 | time to: NO_TIME_OUT. |
---|
| 207 | |
---|
| 208 | @return SOCKET_NOT_OPEN, NON_BLOCKING_HAS_NO_DATA, TIMED_OUT, CONNECTION_TERMINATED, OK, errno |
---|
| 209 | */ |
---|
| 210 | int read(char *ptr, int *nbytes, int blockingType); |
---|
| 211 | |
---|
| 212 | /** Allows you to change the parameters to the setsockopt() options.Currently this member allows you to change socket buffer size. |
---|
| 213 | |
---|
| 214 | @param option |
---|
| 215 | Specify QUANTAnet_tcpClient_c::READ_BUFFER_SIZE if you want to change the size of the receive buffer. |
---|
| 216 | Specify QUANTAnet_tcpClient_c::WRITE_BUFFER_SIZE if you want to change the size of the send buffer |
---|
| 217 | |
---|
| 218 | @param buffersize |
---|
| 219 | Specify the size. |
---|
| 220 | */ |
---|
| 221 | void setSockOptions(int option, int buffersize); |
---|
| 222 | |
---|
| 223 | |
---|
| 224 | /** Determines if a socket has data available to read. |
---|
| 225 | @return Either: QUANTAnet_tcpClient_c::NOT_READY |
---|
| 226 | or QUANTAnet_tcpClient_c::READY_TO_READ |
---|
| 227 | */ |
---|
| 228 | int isReadyToRead(); |
---|
| 229 | |
---|
| 230 | /** Determines if a socket is ready to write. |
---|
| 231 | @return Either: QUANTAnet_tcpClient_c::NOT_READY |
---|
| 232 | or QUANTAnet_tcpClient_c::READY_TO_WRITE |
---|
| 233 | */ |
---|
| 234 | int isReadyToWrite(); |
---|
| 235 | |
---|
| 236 | /** Determines if a socket is ready to write or read or both. |
---|
| 237 | @return Either: QUANTAnet_tcpClient_c::NOT_READY |
---|
| 238 | or QUANTAnet_tcpClient_c::READY_TO_WRITE |
---|
| 239 | or QUANTAnet_tcpClient_c::READY_TO_READ |
---|
| 240 | or QUANTAnet_tcpClient_c::READY_TO_READ_AND_WRITE |
---|
| 241 | */ |
---|
| 242 | int isReady(); |
---|
| 243 | |
---|
| 244 | /** Write data to socket. |
---|
| 245 | @return SOCKET_NOT_OPEN, NON_BLOCKING_NOT_READY_TO_WRITE, TIMED_OUT, CONNECTION_TERMINATED, OK |
---|
| 246 | */ |
---|
| 247 | int write(const char *ptr, int *nbytes, int blockingType); |
---|
| 248 | |
---|
| 249 | /// Show status of connection in English. |
---|
| 250 | void showStatus(int status, int nbytes); |
---|
| 251 | |
---|
| 252 | /// Close the current client connection. |
---|
| 253 | int close(); |
---|
| 254 | |
---|
| 255 | /** Connect to a server. |
---|
| 256 | @return A negative number(that is returned by a socket sonnect() call if failed. |
---|
| 257 | Else returns client's socket file descriptor. (note: the return value in the previous |
---|
| 258 | versions was a zero in case of an error - this has been changed to a negative value from version 1.2) |
---|
| 259 | */ |
---|
| 260 | int connectToServer(const char *ip, int port); |
---|
| 261 | |
---|
| 262 | |
---|
| 263 | //Functions added for performance monitoring interface |
---|
| 264 | /** |
---|
| 265 | Displays the resultant statistics instantaneously in the netlogger format - |
---|
| 266 | this should be typically done after a read/write is done over a network. |
---|
| 267 | |
---|
| 268 | Also, it should be noted that a showStats call should be made at the end of atleast one send |
---|
| 269 | and receive for two-way information (the same applies for logStats and sendStats) |
---|
| 270 | |
---|
| 271 | @param streamInfo |
---|
| 272 | A label describing the stream that is being monitored. |
---|
| 273 | |
---|
| 274 | @param comment |
---|
| 275 | A comment on the event that marks the time at which the stream is being monitored |
---|
| 276 | */ |
---|
| 277 | |
---|
| 278 | void showStats(char* streamInfo, char* comment); |
---|
| 279 | |
---|
| 280 | /** |
---|
| 281 | This logs performance statistics in a file. The user opens a file and passes the file pointer |
---|
| 282 | with this function and results of monitoring are written into the logfile. |
---|
| 283 | |
---|
| 284 | @param streamInfo |
---|
| 285 | A label describing the stream that is being monitored. |
---|
| 286 | |
---|
| 287 | @param comment |
---|
| 288 | A comment on the event that marks the time at which the stream is being monitored |
---|
| 289 | |
---|
| 290 | @param filePtr |
---|
| 291 | File pointer to the file in which the results of monitoring are to be stored |
---|
| 292 | |
---|
| 293 | @return |
---|
| 294 | Either QUANTAnet_perfMonitor_c::OK or QUANTAnet_perfMonitor_c::FAILED |
---|
| 295 | */ |
---|
| 296 | |
---|
| 297 | |
---|
| 298 | int logStats(char* streamInfo, char* comment, FILE* filePtr); |
---|
| 299 | |
---|
| 300 | /** |
---|
| 301 | Sends the performance statistics to a remote perfdaemon -for further analysis of the monitored data - |
---|
| 302 | the initSendStats API should be called first, before calling a sendStats (In order to connect to the perfdaemon initially) |
---|
| 303 | |
---|
| 304 | @param streamInfo |
---|
| 305 | A label describing the stream that is being monitored. |
---|
| 306 | |
---|
| 307 | @param comment |
---|
| 308 | A comment on the event that marks the time at which the stream is being monitored |
---|
| 309 | |
---|
| 310 | @return |
---|
| 311 | Either QUANTAnet_perfMonitor_c::OK or QUANTAnet_perfMonitor_c::FAILED |
---|
| 312 | |
---|
| 313 | */ |
---|
| 314 | |
---|
| 315 | int sendStats(char* streamInfo, char* comment); |
---|
| 316 | |
---|
| 317 | /** |
---|
| 318 | Initialize sendStats - provide the IP of the perfDaemon and an optional port number to connect to. |
---|
| 319 | This should be done initially before using the sendStats API. |
---|
| 320 | |
---|
| 321 | @param monitorClientIP |
---|
| 322 | IP address of the perfDameon to connect to |
---|
| 323 | |
---|
| 324 | @param port |
---|
| 325 | Port number at which the perfDaemon is running -this is optional. The default port number for perfDaemon is 9500 |
---|
| 326 | -so a different port number has to be specified if the perfDaemon is running ona different port. |
---|
| 327 | |
---|
| 328 | @return |
---|
| 329 | Either QUANTAnet_perfMonitor_c::OK or QUANTAnet_perfMonitor_c::FAILED |
---|
| 330 | */ |
---|
| 331 | |
---|
| 332 | int initSendStats(const char* monitorClientIP, int port = PERF_DAEMON_DEFAULT_PORT); |
---|
| 333 | |
---|
| 334 | /** |
---|
| 335 | Properly delete the perFDaemon Client after sendStats is done |
---|
| 336 | */ |
---|
| 337 | |
---|
| 338 | void exitSendStats(); |
---|
| 339 | |
---|
| 340 | //Set the instantaneous latency |
---|
| 341 | void setInstantaneousLatency(double latency); |
---|
| 342 | |
---|
| 343 | /** |
---|
| 344 | @param q_iovec QUANTAnet_iovec_c |
---|
| 345 | @param blockingtype QUANTAnet_tcpClient_c::BLOCKING or, NON_BLOCKING |
---|
| 346 | @return 1 if succed, or errno if fails |
---|
| 347 | comment:readv gives bad address error when iovec pointer is not initialized. |
---|
| 348 | */ |
---|
| 349 | int readv(QUANTAnet_iovec_c q_iovec, int blockingType); |
---|
| 350 | |
---|
| 351 | |
---|
| 352 | /** |
---|
| 353 | @param q_iovec QUANTAnet_iovec_c |
---|
| 354 | @param blockingtype QUANTAnet_tcpClient_c::BLOCKING or, NON_BLOCKING |
---|
| 355 | @return 1 if succed, or errno if fails |
---|
| 356 | comment:writev gives invalid argument error when iovec length is not initialized. |
---|
| 357 | */ |
---|
| 358 | int writev(QUANTAnet_iovec_c q_iovec, int blockingType); |
---|
| 359 | }; |
---|
| 360 | |
---|
| 361 | /** TCP Class for creating servers. This class bypasses QUANTA's standard method for |
---|
| 362 | establishing connections and provides the user with direct control of TCP connections. |
---|
| 363 | */ |
---|
| 364 | |
---|
| 365 | class QUANTAnet_tcpServer_c : public QUANTAnet_socketbase_c { |
---|
| 366 | |
---|
| 367 | |
---|
| 368 | protected: |
---|
| 369 | int serverPort; |
---|
| 370 | |
---|
| 371 | int timeOutPeriod; |
---|
| 372 | int sockfd; |
---|
| 373 | struct sockaddr_in serverInfo; |
---|
| 374 | |
---|
| 375 | public: |
---|
| 376 | |
---|
| 377 | //@{ |
---|
| 378 | /// Status ok. |
---|
| 379 | static const int OK/* = 1*/; |
---|
| 380 | |
---|
| 381 | /// Status failed. |
---|
| 382 | static const int FAILED/* = 0*/; |
---|
| 383 | |
---|
| 384 | /// Change the socket buffer size before read(). |
---|
| 385 | static const int READ_BUFFER_SIZE/* = 2*/; |
---|
| 386 | |
---|
| 387 | /// Change the socket buffer size before write(). |
---|
| 388 | static const int WRITE_BUFFER_SIZE/* = 3*/; |
---|
| 389 | |
---|
| 390 | //@} |
---|
| 391 | |
---|
| 392 | // static int QUANTAnet_tcpServer_c::NO_TIME_OUT; |
---|
| 393 | |
---|
| 394 | /** Set timeout period when performing read() or write() operations. |
---|
| 395 | @param t Time out period in seconds. Set to QUANTAnet_tcpClient_c::NO_TIME_OUT to set no time out period. |
---|
| 396 | */ |
---|
| 397 | void setTimeOut(int t) {timeOutPeriod = t;} |
---|
| 398 | |
---|
| 399 | /// Get timeout period. |
---|
| 400 | int getTimeOut() {return timeOutPeriod;} |
---|
| 401 | |
---|
| 402 | QUANTAnet_tcpServer_c(); |
---|
| 403 | virtual ~QUANTAnet_tcpServer_c() { if (sockfd) close(); } |
---|
| 404 | |
---|
| 405 | /// Get server's port. |
---|
| 406 | int getSelfPort() { |
---|
| 407 | return ntohs(serverInfo.sin_port); |
---|
| 408 | } |
---|
| 409 | |
---|
| 410 | /** Open the server on a port. |
---|
| 411 | Typically after this call you sit in a loop and call |
---|
| 412 | checkForNewConnections to wait for incoming connections. |
---|
| 413 | @return FAILED if failed, OK if success |
---|
| 414 | */ |
---|
| 415 | int init(int port); |
---|
| 416 | |
---|
| 417 | /** Allows you to change the parameters to the setsockopt() options.Currently this member allows you to change socket buffer size. |
---|
| 418 | |
---|
| 419 | @param option |
---|
| 420 | Specify QUANTAnet_tcpServer_c::READ_BUFFER_SIZE if you want to change the size of the receive buffer. |
---|
| 421 | Specify QUANTAnet_tcpServer_c::WRITE_BUFFER_SIZE if you want to change the size of the send buffer |
---|
| 422 | |
---|
| 423 | @param buffersize |
---|
| 424 | Specify the size. |
---|
| 425 | */ |
---|
| 426 | void setSockOptions(int option, int buffersize); |
---|
| 427 | |
---|
| 428 | /// Close the server port. |
---|
| 429 | int close(); |
---|
| 430 | |
---|
| 431 | /** Check to see if there is a request from clients for connection. |
---|
| 432 | This function checks for new connections. If there is a |
---|
| 433 | new connection, then a new QUANTAnet_tcpClient_c object is |
---|
| 434 | returned, and that object can be used to talk to the new |
---|
| 435 | client. |
---|
| 436 | |
---|
| 437 | @param blockingTime time to block while checking |
---|
| 438 | @return a new QUANTAnet_tcpClient_c object |
---|
| 439 | @see QUANTAnet_tcpClient_c class. |
---|
| 440 | */ |
---|
| 441 | QUANTAnet_tcpClient_c* checkForNewConnections(const int& blockingTime=0); |
---|
| 442 | |
---|
| 443 | /** Blocks while waiting for a new connection. |
---|
| 444 | While waiting for new connections to arrive, the server blocks |
---|
| 445 | until a new client has connected. This blocking wait results in |
---|
| 446 | better performance than the checkForNewConnections |
---|
| 447 | implementation. The server will block until a new client has |
---|
| 448 | connected, and when a client connects, a pointer to the new |
---|
| 449 | client object is returned. |
---|
| 450 | |
---|
| 451 | @return a new QUANTAnte_tcpClient_c object |
---|
| 452 | @see QUANTAnet_tcpClient_c class. |
---|
| 453 | */ |
---|
| 454 | QUANTAnet_tcpClient_c* waitForNewConnection(); |
---|
| 455 | |
---|
| 456 | }; |
---|
| 457 | |
---|
| 458 | #endif |
---|