非同期型ソケット関数を使用したTCPサーバーのサンプルプログラムです。

 接続先のアクセスポイントはシステムメニューで設定してください。

動作概要

  1. [ENT]キーを押すと無線LANを有効にします。
  2. アクセスポイントに接続したら、TCPサーバー自身のIPアドレスを表示します。
  3. TCPサーバーは、TCPクライアントが接続するのを待機します。(BindSc関数, ListenSc関数)
  4. TCPクライアントが接続すると、受信を開始します。(RecvSc関数)
  5. TCPクライアントからのデータを受信すると、"OK<CR>"を送信します。(SendSc関数)
  6. 送信が成功すると、TCPクライアントとのソケットを切断し、3.に戻ります。(CloseSc関数)
無線LANが有効の間に[BS]キーを押すと、TCPサーバー動作を終了し、無線LANを無効にします。

サンプル
#include <stdio.h>
#include <string.h>
#include "lib.h"
#include "logapi.h"

#define LISTEN_PORT      20080
#define TCPSV_BUFFER_MAX 1500
#define LOG_TCPSV 1
#define RESPONSE_MESSAGE "OK\n"

enum
{
    TCPSV_STATE_INIT = 0,
    TCPSV_STATE_BIND,
    TCPSV_STATE_LISTEN,
    TCPSV_STATE_ACCEPT,
    TCPSV_STATE_ACCEPTED
};
enum
{
    TCP_RECV_STATE_INIT = 0,
    TCP_RECV_STATE_READY,
    TCP_RECV_STATE_RECEIVED,
};
enum
{
    TCP_SEND_STATE_INIT = 0,
    TCP_SEND_STATE_READY,
    TCP_SEND_STATE_SENDING,
    TCP_SEND_STATE_SENT,
};
static unsigned char recvBuffer[TCPSV_BUFFER_MAX];
static unsigned char sendBuffer[TCPSV_BUFFER_MAX];
static short recvSize;
static short sendSize;
static short sendResult = 0;
static SOCKET listenSocket;
static SOCKET peerSocket;
static unsigned char tcpsvState;
static unsigned char recvState;
static unsigned char sendState;
static unsigned char requestReset;

static void TcpSvInit(void)
{
    recvSize = 0;
    listenSocket = -1;
    peerSocket = -1;
    tcpsvState = TCPSV_STATE_INIT;
    recvState = TCP_RECV_STATE_INIT;
    sendState = TCP_SEND_STATE_INIT;
    requestReset = FALSE;
    memset(recvBuffer, 0, sizeof(recvBuffer));
}
static void socket_cb(SOCKET sock, unsigned char u8Msg, void *pvMsg)
{
    if (sock == listenSocket){
        switch (u8Msg)
        {
        case SOCKET_MSG_BIND:
            if (pvMsg != NULL){
                tstrSocketBindMsg *pstrBind = (tstrSocketBindMsg *)pvMsg;
                LOG_PRINTF(LOG_TCPSV, "SOCKET_MSG_BIND sock=%d status=%d", sock, pstrBind->status);
                if (pstrBind->status == 0){
                    if (ListenSc(listenSocket, 0) != SOCK_ERR_NO_ERROR){
                        CloseSc(listenSocket);
                        listenSocket = -1;
                        requestReset = TRUE;
                    }
                    tcpsvState = TCPSV_STATE_LISTEN;
                }else{
                    CloseSc(listenSocket);
                    listenSocket = -1;
                }
            }
            break;
        case SOCKET_MSG_LISTEN:
            if (pvMsg != NULL){
                tstrSocketListenMsg *pstrListen = (tstrSocketListenMsg *)pvMsg;
                LOG_PRINTF(LOG_TCPSV, "SOCKET_MSG_LISTEN sock=%d status=%d", sock, pstrListen->status);
                if (pstrListen->status == 0){
                    tcpsvState = TCPSV_STATE_ACCEPT;
                }else{
                    CloseSc(listenSocket);
                    listenSocket = -1;
                }
            }
            break;
        case SOCKET_MSG_ACCEPT:
            if (pvMsg != NULL){
                tstrSocketAcceptMsg *pstrAccept = (tstrSocketAcceptMsg *)pvMsg;
                unsigned char *peerIP = (unsigned char *)&(pstrAccept->strAddr.sin_addr.s_addr);
                LOG_PRINTF(LOG_TCPSV, "SOCKET_MSG_LISTEN sock=%d accept sock=%d IP=%d.%d.%d.%d",
                    sock, pstrAccept->sock, peerIP[0], peerIP[1], peerIP[2], peerIP[3]);
                if (pstrAccept){
                    peerSocket = pstrAccept->sock;
                    if (peerSocket >= 0 && peerSocket < TCP_SOCK_MAX){
                        tcpsvState = TCPSV_STATE_ACCEPTED;
                        sendState = TCP_SEND_STATE_READY;
                    }
                }else{
                    CloseSc(listenSocket);
                    listenSocket = -1;
                }
            }
            break;
        default:
            LOG_PRINTF(LOG_TCPSV, "sock=%d u8msg=%d pvMsg=0x%x", sock, u8Msg, pvMsg);
            break;
        }
    }else if(sock == peerSocket){
        switch (u8Msg)
        {
        case SOCKET_MSG_SEND:
            if (pvMsg != NULL){
                sendResult = *(short *)pvMsg;
                LOG_PRINTF(LOG_TCPSV, "SOCKET_MSG_SEND sock=%d length=%d", sendResult);
                if (sendResult <= 0){
                    CloseSc(peerSocket);
                    peerSocket = -1;
                    CloseSc(listenSocket);
                    listenSocket = -1;
                    recvState = TCP_RECV_STATE_INIT;
                    sendState = TCP_SEND_STATE_INIT;
                }else{
                    sendState = TCP_SEND_STATE_SENT;
                }
            }
            break;
        case SOCKET_MSG_RECV:
            if (pvMsg != NULL){
                tstrSocketRecvMsg *pstrRecv = (tstrSocketRecvMsg *)pvMsg;
                LOG_PRINTF(LOG_TCPSV, "SOCKET_MSG_RECV sock=%d s16BufferSize=%d u16RemainingSize=%d pu8Buffer:%s",
                    sock, pstrRecv->s16BufferSize, pstrRecv->u16RemainingSize, pstrRecv->pu8Buffer);
                recvSize = pstrRecv->s16BufferSize;
                if (pstrRecv->s16BufferSize > (int)sizeof(recvBuffer) ||
                    pstrRecv->s16BufferSize <= 0){
                    CloseSc(peerSocket);
                    peerSocket = -1;
                    CloseSc(listenSocket);
                    listenSocket = -1;
                    recvState = TCP_RECV_STATE_INIT;
                    sendState = TCP_SEND_STATE_INIT;
                }else{
                    recvState = TCP_RECV_STATE_RECEIVED;
                }
            }
            break;
        default:
            LOG_PRINTF(LOG_TCPSV, "sock=%d u8msg=%d pvMsg=0x%x", sock, u8Msg, pvMsg);
            break;
        }
    }
}

void main(void)
{
    char key;
    int wlanPowerState = OFF;
    int wlanConnect = SYS_WLAN_STATUS_UNAVAILABLE;
    int prevWlanConnect;
    long brText;
    tstrM2MConnInfo conInfo;
    unsigned char tcpsvPrevState;
    struct sockaddr_in addr;

    addr.sin_family = AF_INET;
    addr.sin_port = _htons(LISTEN_PORT);
    addr.sin_addr.s_addr = 0;
    memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
    printf( "TCP SERVER\n" );
    while (1){
        if (wlanPowerState == OFF){
            SysSetWLANPower(SYS_WLAN_POWER_OFF);
            ResetKey();
            printf( "\fENT to start server\n" );
            while (1){
                if (kbhit()){
                    if (getchar() == ENT_KEY){
                        wlanPowerState = ON;
                        break;
                    }
                }
                Idle();
            }
        }else{
            printf( "\fStart TCP server\n" );
            printf( "BS to end\n" );
            SysSetWLANPower(SYS_WLAN_POWER_AUTO);
            SysWLANInit(NULL);
            InitSc();
            TcpSvInit();
            RegSocketCallbackSc(socket_cb, NULL);
            tcpsvPrevState = tcpsvState;
            prevWlanConnect = SYS_WLAN_STATUS_UNAVAILABLE;
            while (1){
                if (requestReset == TRUE){
                    break;
                }
                if (kbhit()){
                    key = getchar();
                    if (key == BS_KEY){
                        wlanPowerState = OFF;
                        break;
                    }
                }
                while (1){
                    SysGetWLANConnectStatus(&wlanConnect);
                    if (wlanConnect == SYS_WLAN_STATUS_CONNECTED){
                        if (wlanConnect != prevWlanConnect){
                            if (SysGetConnectInfoWlan(&conInfo) == TRUE){
                                prevWlanConnect = wlanConnect;
                                printf("Wlan connected\nIP:%d.%d.%d.%d\n",
                                    conInfo.au8IPAddr[0], conInfo.au8IPAddr[1], conInfo.au8IPAddr[2], conInfo.au8IPAddr[3]);
                                LOG_PRINTF(LOG_TCPSV, "Wlan connected IP:%d.%d.%d.%d",
                                    conInfo.au8IPAddr[0], conInfo.au8IPAddr[1], conInfo.au8IPAddr[2], conInfo.au8IPAddr[3]);
                            }
                        }
                        break;
                    }
                    if (kbhit()){
                        if (getchar() == BS_KEY){
                            wlanPowerState = OFF;
                            break;
                        }
                    }
                    Idle();
                }
                if (tcpsvState != tcpsvPrevState){
                    LOG_PRINTF(LOG_TCPSV, "State:%d", tcpsvState);
                    tcpsvPrevState = tcpsvState;
                    if (tcpsvState == TCPSV_STATE_ACCEPTED){
                        printf("Socket connected\n");
                        // Start receive ----------
                        if (RecvSc(peerSocket, recvBuffer, sizeof(recvBuffer), 0) != SOCK_ERR_NO_ERROR){
                            requestReset = TRUE;
                        }else{
                            recvState = TCP_RECV_STATE_READY;
                        }
                        // ------------------------
                    }
                }
                if (listenSocket < 0){
                    if ((listenSocket = SocketSc(AF_INET, SOCK_STREAM, 0)) < 0){
                        requestReset = TRUE;
                        continue;
                    }
                    if (BindSc(listenSocket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) != SOCK_ERR_NO_ERROR){
                        requestReset = TRUE;
                        continue;
                    }
                    tcpsvState = TCPSV_STATE_BIND;
                }
                if (recvState == TCP_RECV_STATE_RECEIVED && recvSize > 0){
                    LOG_PRINTF(LOG_TCPSV, "recv:%s", recvBuffer);
                    // Show receive data
                    brText = SetTextColor(RGB_RED);
                    printf("%s", recvBuffer);
                    SetTextColor(brText);
                    // Clear receive buffer
                    memset(recvBuffer, 0, sizeof(recvBuffer));
                    recvSize = 0;
                    // Set send message --------------------
                    strcpy(sendBuffer, RESPONSE_MESSAGE);
                    sendSize = strlen(RESPONSE_MESSAGE);
                    // -------------------------------------
                }
                if (sendState == TCP_SEND_STATE_READY){
                    if (sendSize > 0){
                        // Send message
                        if (SendSc(peerSocket, sendBuffer, sendSize, 0) != SOCK_ERR_NO_ERROR){
                            requestReset = TRUE;
                            sendSize = 0;
                            continue;
                        }
                        LOG_PRINTF(LOG_TCPSV, "send:%s", sendBuffer);
                        brText = SetTextColor(RGB_BLUE);
                        printf("%s", sendBuffer);
                        SetTextColor(brText);
                        // Clear send buffer
                        memset(sendBuffer, 0, sizeof(sendBuffer));
                        sendSize = 0;
                        sendState = TCP_SEND_STATE_SENDING;
                    }
                }else if (sendState == TCP_SEND_STATE_SENT){
                    // Disconnect peer socket -----
                    printf("Socket close\n");
                    CloseSc(peerSocket);
                    peerSocket = -1;
                    recvState = TCP_RECV_STATE_INIT;
                    sendState = TCP_SEND_STATE_INIT;
                    tcpsvState = TCPSV_STATE_ACCEPT;
                    // ----------------------------
                }
                Idle();
            }
        }
        Idle();
    }
}

最終更新日:2020/12/20