Machine Vision Status TCP Server

Dependencies:   C12832 EthernetInterface mbed-rtos mbed ConfigFile

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?

UserRevisionLine numberNew 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 }