服务器端的Websocket在重新加载后断开连接

时间:2015-04-26 18:45:07

标签: c sockets websocket network-programming connection

我最近在C中使用名为cwebsockets的库来处理websockets,现在可以向客户端发送消息了。问题是只要重新加载客户端的页面,应用程序就会关闭。我希望服务器端在上次连接由于重新加载而丢失之后查找新连接。

我得到的消息是send failed: connection reset by peer,我在一些研究之后理解的是发件人没有得到客户的确认。但我该怎么处理呢?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <errno.h>
#include <signal.h>
#include "websocket.h"

#define PORT                8081
#define BUF_LEN             0xFFFF 
#define FILE_BUF_SIZE       30

void error(const char *msg) {
    perror(msg);
    exit(EXIT_FAILURE);
}

int safeSend(int clientSocket, const uint8_t *buffer, size_t bufferSize) {
    #ifdef PACKET_DUMP
    printf("out packet:\n");
    fwrite(buffer, 1, bufferSize, stdout);
    printf("\n");
    #endif
    ssize_t written = send(clientSocket, buffer, bufferSize, 0);
    if (written == -1) {
        close(clientSocket);
        perror("send failed");
        return EXIT_FAILURE;
    }
    if (written != bufferSize) {
        close(clientSocket);
        perror("written not all bytes");
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS; 
}

void clientWorker(int clientSocket) {
    FILE *f;
    unsigned char f_ch_a_buf[FILE_BUF_SIZE];
    unsigned char f_ch_b_buf[FILE_BUF_SIZE];
    short *ch_a_data = (short*)f_ch_a_buf;
    short *ch_b_data = (short*)f_ch_b_buf;
    int n,i;

    int memfd;
    void *map_base, *virt_addr;
    short *ch_data;

    uint8_t buffer[BUF_LEN];
    memset(buffer, 0, BUF_LEN);
    size_t readedLength = 0;
    size_t frameSize = BUF_LEN;
    enum wsState state = WS_STATE_OPENING;
    uint8_t *data = NULL;
    size_t dataSize = 0;
    enum wsFrameType frameType = WS_INCOMPLETE_FRAME;
    struct handshake hs;
    nullHandshake(&hs);

    uint8_t msg[BUF_LEN];

    #define prepareBuffer frameSize = BUF_LEN; memset(buffer, 0, BUF_LEN);
    #define initNewFrame frameType = WS_INCOMPLETE_FRAME; readedLength = 0; memset(buffer, 0, BUF_LEN);

    while (frameType == WS_INCOMPLETE_FRAME) {
        ssize_t readed = recv(clientSocket, buffer+readedLength, BUF_LEN-readedLength, 0);
        if(readed <= 0){
            if(state == WS_STATE_NORMAL){
            /*
            temp_raw = sys_file_read("/sys/devices/soc0/amba/f8007100.adc/iio:device0/in_temp0_raw");
            temp_scale = sys_file_read("/sys/devices/soc0/amba/f8007100.adc/iio:device0/in_temp0_scale");
            temp_offset = sys_file_read("/sys/devices/soc0/amba/f8007100.adc/iio:device0/in_temp0_offset");

            // Formel brukt for å regne SoC temperatur: (in_temp0_raw - temp_offset)/temp_scale 
            dash_temp = ((temp_raw - temp_offset)/temp_scale);
            */

            int EXTS[8];
            int CPS[8];
            int CAM[4];
            int i;
            for(i=0;i<8;i++){
                EXTS[i] = (double)rand() / RAND_MAX;
            }
            for(i=0;i<8;i++){
                CPS[i] = rand() % 30 + 2;
            }
            for(i=0;i<8;i++){
                CAM[i] = rand() % 30 + 2;
            }

            int dash_kmt = rand() % 9 + 35;
            int FSS1 = rand() % 1 + 4;
            int FTWS2 = rand() % 2 + 90;
            int FPFS2 = 28.5;
            int MAP = rand() % 10 + 120;

            int FTFS1 = rand() % 5 + 50;
            int FTOS3 = rand() % 5 + 50;
            int FPOS1 = rand() % 5 + 50;        

            int TPDS1 = rand() % 5 + 50;        
            int TPAS2 = rand() % 5 + 50;        

            int MAF = rand() % 5 + 50;          
            int ATFS2 = rand() % 5 + 50;        

            int TDC2S2 = rand() % 5 + 10;
            int L1S1 = rand() % 5 + 10;
            int L2S2 = rand() % 5 + 10;
            int K1S1 = rand() % 5 + 10;
            int K2S2  = rand() % 5 + 15;

                dataSize = sprintf((char *)msg, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", 
                    dash_kmt,FSS1,FTWS2,FPFS2,MAP,EXTS[0],EXTS[1],EXTS[2],EXTS[3],EXTS[4],EXTS[5],EXTS[6],EXTS[7],
                    CPS[0],CPS[1],CPS[2],CPS[3],CPS[4],CPS[5],CPS[6],CPS[7],CAM[1],CAM[2],CAM[3],CAM[4],
                    FTFS1, FTOS3, FPOS1, TPDS1, TPAS2, MAF, ATFS2, TDC2S2, L1S1, L2S2, K1S1, K2S2
                );
                usleep(1000);

                prepareBuffer;
                wsMakeFrame(msg, dataSize, buffer, &frameSize, WS_TEXT_FRAME);
                if (safeSend(clientSocket, buffer, frameSize) == EXIT_FAILURE)
                    break;
                initNewFrame;
            }
        }

        if(readed > 0){
        readedLength+= readed;
        assert(readedLength <= BUF_LEN);

        if (state == WS_STATE_OPENING) {
            frameType = wsParseHandshake(buffer, readedLength, &hs);
        } else {
            frameType = wsParseInputFrame(buffer, readedLength, &data, &dataSize);
        }

        if ((frameType == WS_INCOMPLETE_FRAME && readedLength == BUF_LEN) || frameType == WS_ERROR_FRAME) {
            if (frameType == WS_INCOMPLETE_FRAME)
                printf("buffer too small");
            else
                printf("error in incoming frame\n");

            if (state == WS_STATE_OPENING) {
                prepareBuffer;
                frameSize = sprintf((char *)buffer,
                                    "HTTP/1.1 400 Bad Request\r\n"
                                    "%s%s\r\n\r\n",
                                    versionField,
                                    version);
                safeSend(clientSocket, buffer, frameSize);
                break;
            } else {
                prepareBuffer;
                wsMakeFrame(NULL, 0, buffer, &frameSize, WS_CLOSING_FRAME);
                if (safeSend(clientSocket, buffer, frameSize) == EXIT_FAILURE)
                    break;
                state = WS_STATE_CLOSING;
                initNewFrame;
            }
        }
        if (state == WS_STATE_OPENING) {
            assert(frameType == WS_OPENING_FRAME);
            if (frameType == WS_OPENING_FRAME) {
                // if resource is right, generate answer handshake and send it
                if (strcmp(hs.resource, "/osc") != 0) {
                    frameSize = sprintf((char *)buffer, "HTTP/1.1 404 Not Found\r\n\r\n");
                    if (safeSend(clientSocket, buffer, frameSize) == EXIT_FAILURE)
                        break;
                }

                prepareBuffer;
                wsGetHandshakeAnswer(&hs, buffer, &frameSize);
                if (safeSend(clientSocket, buffer, frameSize) == EXIT_FAILURE)
                    break;
                state = WS_STATE_NORMAL;
                initNewFrame;
            }
        } else {
            if (frameType == WS_CLOSING_FRAME) {
                if (state == WS_STATE_CLOSING) {
                    break;
                } else {
                    prepareBuffer;
                    wsMakeFrame(NULL, 0, buffer, &frameSize, WS_CLOSING_FRAME);
                    safeSend(clientSocket, buffer, frameSize);
                    break;
                }
            } else if (frameType == WS_TEXT_FRAME) {
                uint8_t *recievedString = NULL;
                recievedString = malloc(dataSize+1);
                assert(recievedString);
                memcpy(recievedString, data, dataSize);
                recievedString[ dataSize ] = 0;

                wsMakeFrame(recievedString, dataSize, buffer, &frameSize, WS_TEXT_FRAME);
                if (safeSend(clientSocket, buffer, frameSize) == EXIT_FAILURE)
                    break;
                initNewFrame;
            }
        }
        }
    }
    close(clientSocket);
}

int main(int argc, char** argv)
{
    int i;
    int listenSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (listenSocket == -1) {
        error("create socket failed");
    }

    struct sockaddr_in local;
    memset(&local, 0, sizeof(local));
    local.sin_family = AF_INET;
    local.sin_addr.s_addr = INADDR_ANY;
    local.sin_port = htons(PORT);
    if (bind(listenSocket, (struct sockaddr *) &local, sizeof(local)) == -1) {
        error("bind failed");
    }

    if (listen(listenSocket, 1) == -1) {
        error("listen failed");
    }
#ifdef DEBUG
    printf("opened %s:%d\n", inet_ntoa(local.sin_addr), ntohs(local.sin_port));
#endif

    while (TRUE) {
        struct sockaddr_in remote;
        socklen_t sockaddrLen = sizeof(remote);
        int clientSocket = accept(listenSocket, (struct sockaddr*)&remote, &sockaddrLen);
        if (clientSocket == -1) {
            error("accept failed");
        }
#ifdef DEBUG        
        printf("Websocket server: Connected %s:%d\n", inet_ntoa(remote.sin_addr), ntohs(remote.sin_port));
#endif
        if(fcntl(clientSocket, F_SETFL, fcntl(clientSocket, F_GETFL) | O_NONBLOCK) < 0) {
            // handle error
            printf("Error to put socket in non-blocking mode\n");
        }
        clientWorker(clientSocket);
#ifdef DEBUG
        printf("Websocket server: Disconnected\n");
#endif
    }
    close(listenSocket);
    return EXIT_SUCCESS;
}

0 个答案:

没有答案