Machine Vision Status TCP Server
Dependencies: C12832 EthernetInterface mbed-rtos mbed ConfigFile
TcpDaemon.cpp@3:254a2671a8e3, 2015-03-06 (annotated)
- Committer:
- dwini
- Date:
- Fri Mar 06 08:20:56 2015 +0000
- Revision:
- 3:254a2671a8e3
- Parent:
- 2:a8eebf64cd3e
- Child:
- 4:339a85b66476
Change to non-blocking accept. Fix client disconnection bug.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
dwini | 1:8efef658d90b | 1 | #include "TcpDaemon.h" |
dwini | 1:8efef658d90b | 2 | #include "Log.h" |
dwini | 1:8efef658d90b | 3 | |
dwini | 2:a8eebf64cd3e | 4 | // Incoming message end |
dwini | 1:8efef658d90b | 5 | #define END_MSG_SEQUENCE "\r\n" |
dwini | 1:8efef658d90b | 6 | |
dwini | 1:8efef658d90b | 7 | namespace MachineVision{ |
dwini | 1:8efef658d90b | 8 | /* |
dwini | 1:8efef658d90b | 9 | * TcpDaemon constructor |
dwini | 1:8efef658d90b | 10 | * |
dwini | 1:8efef658d90b | 11 | * @server_port the port the daemon will be listening on |
dwini | 1:8efef658d90b | 12 | */ |
dwini | 3:254a2671a8e3 | 13 | TcpDaemon::TcpDaemon(int server_port, PinName accept_led_pin, PinName receive_led_pin) |
dwini | 3:254a2671a8e3 | 14 | : receive_led(receive_led_pin), accept_led(accept_led_pin) { |
dwini | 1:8efef658d90b | 15 | this->server_port = server_port; |
dwini | 1:8efef658d90b | 16 | this->keepListening = true; |
dwini | 2:a8eebf64cd3e | 17 | this->receive_led = 0; |
dwini | 3:254a2671a8e3 | 18 | this->accept_led = 0; |
dwini | 1:8efef658d90b | 19 | } |
dwini | 1:8efef658d90b | 20 | |
dwini | 1:8efef658d90b | 21 | /* |
dwini | 1:8efef658d90b | 22 | * Make the daemon start listening for incoming connections |
dwini | 1:8efef658d90b | 23 | */ |
dwini | 1:8efef658d90b | 24 | void TcpDaemon::startListening() { |
dwini | 1:8efef658d90b | 25 | if (this->bindSocket()) { |
dwini | 1:8efef658d90b | 26 | this->doListen(); |
dwini | 1:8efef658d90b | 27 | } |
dwini | 1:8efef658d90b | 28 | } |
dwini | 1:8efef658d90b | 29 | |
dwini | 1:8efef658d90b | 30 | /* |
dwini | 1:8efef658d90b | 31 | * Bind to server socket |
dwini | 1:8efef658d90b | 32 | * |
dwini | 1:8efef658d90b | 33 | * @return true on success |
dwini | 1:8efef658d90b | 34 | */ |
dwini | 1:8efef658d90b | 35 | bool TcpDaemon::bindSocket() { |
dwini | 1:8efef658d90b | 36 | if(server.bind(server_port) < 0) { |
dwini | 1:8efef658d90b | 37 | Log::e("Bind failed. Error\r\n"); |
dwini | 1:8efef658d90b | 38 | return false; |
dwini | 1:8efef658d90b | 39 | } else { |
dwini | 1:8efef658d90b | 40 | Log::d("Bind ok\r\n"); |
dwini | 3:254a2671a8e3 | 41 | server.set_blocking(false, TCP_ACCEPT_TIMEOUT); // Set tot non-blocking |
dwini | 1:8efef658d90b | 42 | return true; |
dwini | 1:8efef658d90b | 43 | } |
dwini | 1:8efef658d90b | 44 | } |
dwini | 1:8efef658d90b | 45 | |
dwini | 1:8efef658d90b | 46 | /* |
dwini | 1:8efef658d90b | 47 | * Listen for incoming connections |
dwini | 1:8efef658d90b | 48 | */ |
dwini | 1:8efef658d90b | 49 | void TcpDaemon::doListen() { |
dwini | 1:8efef658d90b | 50 | |
dwini | 1:8efef658d90b | 51 | // Listen for incoming connection |
dwini | 1:8efef658d90b | 52 | if (server.listen(MAX_BACKLOG) < 0) { |
dwini | 1:8efef658d90b | 53 | Log::w("Listen failed\r\n"); |
dwini | 1:8efef658d90b | 54 | return; |
dwini | 1:8efef658d90b | 55 | } |
dwini | 1:8efef658d90b | 56 | |
dwini | 3:254a2671a8e3 | 57 | Log::d("Listening for incoming connection ...\r\n"); |
dwini | 1:8efef658d90b | 58 | while (this->keepListening) { |
dwini | 3:254a2671a8e3 | 59 | |
dwini | 3:254a2671a8e3 | 60 | // Visual indication |
dwini | 3:254a2671a8e3 | 61 | accept_led = !accept_led; |
dwini | 1:8efef658d90b | 62 | |
dwini | 1:8efef658d90b | 63 | // Accept connection from an incoming client |
dwini | 3:254a2671a8e3 | 64 | if (server.accept(client) >= 0) { |
dwini | 1:8efef658d90b | 65 | Log::d("Client connected: %s\r\n", client.get_address()); |
dwini | 1:8efef658d90b | 66 | |
dwini | 1:8efef658d90b | 67 | // Set non-blocking |
dwini | 1:8efef658d90b | 68 | client.set_blocking(false, TCP_TIMEOUT); |
dwini | 1:8efef658d90b | 69 | |
dwini | 1:8efef658d90b | 70 | while (client.is_connected()) { |
dwini | 1:8efef658d90b | 71 | // Keep receiving messages from the client |
dwini | 1:8efef658d90b | 72 | int read_size = 0; |
dwini | 1:8efef658d90b | 73 | int total_read_size = 0; |
dwini | 1:8efef658d90b | 74 | char * end = NULL; |
dwini | 2:a8eebf64cd3e | 75 | int i_read = 0; |
dwini | 1:8efef658d90b | 76 | |
dwini | 2:a8eebf64cd3e | 77 | int buffer_size = BUFFER_SIZE; |
dwini | 2:a8eebf64cd3e | 78 | char * buffer_offset = buffer; |
dwini | 2:a8eebf64cd3e | 79 | |
dwini | 2:a8eebf64cd3e | 80 | // Read full message from client |
dwini | 2:a8eebf64cd3e | 81 | Log::v("Waiting for message\r\n"); |
dwini | 2:a8eebf64cd3e | 82 | do { |
dwini | 2:a8eebf64cd3e | 83 | read_size = client.receive(buffer_offset, buffer_size); |
dwini | 2:a8eebf64cd3e | 84 | receive_led = !receive_led; |
dwini | 1:8efef658d90b | 85 | |
dwini | 2:a8eebf64cd3e | 86 | if (read_size > 0) { |
dwini | 2:a8eebf64cd3e | 87 | total_read_size += read_size; |
dwini | 2:a8eebf64cd3e | 88 | |
dwini | 2:a8eebf64cd3e | 89 | // Null-terminate string |
dwini | 2:a8eebf64cd3e | 90 | buffer[total_read_size] = '\0'; |
dwini | 2:a8eebf64cd3e | 91 | Log::v("Received partial: %s\r\n", buffer); |
dwini | 2:a8eebf64cd3e | 92 | |
dwini | 2:a8eebf64cd3e | 93 | // Search for END |
dwini | 2:a8eebf64cd3e | 94 | end = strstr(buffer, END_MSG_SEQUENCE); |
dwini | 2:a8eebf64cd3e | 95 | |
dwini | 2:a8eebf64cd3e | 96 | buffer_size = BUFFER_SIZE-total_read_size; |
dwini | 2:a8eebf64cd3e | 97 | buffer_offset = buffer+total_read_size; |
dwini | 2:a8eebf64cd3e | 98 | } else if (total_read_size > 0) { // Increment i_read (max timeouts for message) |
dwini | 2:a8eebf64cd3e | 99 | i_read++; |
dwini | 2:a8eebf64cd3e | 100 | } |
dwini | 3:254a2671a8e3 | 101 | } while (client.is_connected() && total_read_size < BUFFER_SIZE && end == NULL && i_read < MAX_READ_TIMEOUTS); |
dwini | 1:8efef658d90b | 102 | |
dwini | 3:254a2671a8e3 | 103 | if (end == NULL) { |
dwini | 3:254a2671a8e3 | 104 | if (total_read_size >= BUFFER_SIZE) { |
dwini | 1:8efef658d90b | 105 | Log::w("Buffer full\r\n"); |
dwini | 3:254a2671a8e3 | 106 | } else if (i_read == MAX_READ_TIMEOUTS) { |
dwini | 3:254a2671a8e3 | 107 | Log::w("Partial message received. MAX_READ_TIMEOUTS reached.\r\n"); |
dwini | 1:8efef658d90b | 108 | } |
dwini | 3:254a2671a8e3 | 109 | |
dwini | 3:254a2671a8e3 | 110 | } else { |
dwini | 3:254a2671a8e3 | 111 | // Full string received, lets do our thing |
dwini | 3:254a2671a8e3 | 112 | Log::v("Received: %s\r\n", buffer); |
dwini | 1:8efef658d90b | 113 | } |
dwini | 1:8efef658d90b | 114 | } |
dwini | 1:8efef658d90b | 115 | |
dwini | 1:8efef658d90b | 116 | Log::d("Client disconnected\r\n"); |
dwini | 1:8efef658d90b | 117 | fflush(stdout); |
dwini | 1:8efef658d90b | 118 | client.close(); |
dwini | 1:8efef658d90b | 119 | } |
dwini | 1:8efef658d90b | 120 | } |
dwini | 1:8efef658d90b | 121 | } |
dwini | 1:8efef658d90b | 122 | } |