EthernetInterface, TCP Echo Server, support multi session

Dependencies:   EthernetInterface mbed-rtos mbed

Fork of TCPEchoServer by mbed official

mbed RTOS により、マルチセッションに対応した TCP Echo Server です。

複数のTCP接続を受付け、処理することができます。

accept の後に fork (スレッドを生成)しています。

main.cpp

Committer:
okini3939
Date:
2013-11-07
Revision:
8:46437b951a2f
Parent:
7:0a3cf89d5b93

File content as of revision 8:46437b951a2f:

#include "mbed.h"
#include "rtos.h"
#include "EthernetInterface.h"

#define ECHO_SERVER_PORT   10000

#define THREAD_MAX 5
Thread *threads[THREAD_MAX];
Thread *xthread;

void child (void const *arg) {
    int i;
    char buf[256];
    TCPSocketConnection *client = (TCPSocketConnection*)arg;

    for (;;) {
        printf("Connection from %s\r\n", client->get_address());
//        client->set_blocking(false, 1500); // Timeout after (1.5)s
        for (;;) {
            i = client->receive(buf, sizeof(buf));
            if (i < 0) break;
            if (i == 0) continue;
            buf[i] = 0;
            printf("Recv '%s'\r\n", buf);
            if (client->send(buf, i) < 0) break;
        }

        client->close();
        printf("Close %s\r\n", client->get_address());

        Thread::signal_wait(1);
    }
}

void closer (void const *arg) {
    TCPSocketConnection *client = (TCPSocketConnection*)arg;

    for (;;) {
        client->close();
        printf("Close %s\r\n", client->get_address());

        Thread::signal_wait(1);
    }
}

void parent () {
    int i, t = 0;
    TCPSocketConnection clients[THREAD_MAX];
    TCPSocketConnection xclient;

    for (i = 0; i < THREAD_MAX; i ++) {
        threads[i] = NULL;
    }
    xthread = NULL;

    TCPSocketServer server;
    server.bind(ECHO_SERVER_PORT);
    server.listen();

    printf("Wait for new connection...\r\n");
    for (;;) {
        if (t >= 0) {
            server.accept(clients[t]);
            // fork child process
            if (threads[t]) {
                threads[t]->signal_set(1);
            } else {
                threads[t] = new Thread(child, (void*)&clients[t]);
            }
            printf("Forked %d\r\n", t);
        } else {
            server.accept(xclient);
            // closer process
            if (xthread) {
                xthread->signal_set(1);
            } else {
                xthread = new Thread(closer, (void*)&xclient);
            }
            printf("Connection full\r\n");
        }

        t = -1;
        for (i = 0; i < THREAD_MAX; i ++) {
/*
            if (threads[i]) {
                if (threads[i]->get_state() == Thread::Inactive) {
                    // terminate process
//                    delete threads[i];
//                    threads[i] = NULL;
                    printf("Terminated %d\r\n", i);
                }
            }
*/
            if (threads[i] == NULL || threads[i]->get_state() == Thread::WaitingAnd) {
                if (t < 0) t = i; // next empty thread
            }
        }
    }
}


int main () {
    EthernetInterface eth;
    printf("TCP Echo Server with Fork...\r\n");
    eth.init(); //Use DHCP
    if (eth.connect()) return -1;
    printf("IP Address is %s\r\n", eth.getIPAddress());

    parent();
}