C websocket断开连接

时间:2016-08-04 14:39:08

标签: c websocket

我对websocket有疑问。我有一个特殊的需求,所以,嗅探连续串口(rs485)并将任何数据发送到客户端。 我在互联网上找到了许多帮助,我的书面程序也能正常工作。 我有一个我无法解决的最后一个问题。通常服务器无缘无故地关闭所有客户端的连接并退出c程序。 我必须创建一个虚拟缓冲区以确保所有线程都有数据,因为一旦你读取了串口的缓冲区,它就会被清空。 Websocket服务器在C中,websocket客户端在php / js中。 对不起我糟糕的英语,我很抱歉。 这是我的客户:

var server_connection;
var rs485_connection;
var ping_serverconnection;
var ping_rs485connection
var sockethide=true;

window.addEventListener("beforeunload", function (e) { socketConnection_close(); });

function socketConnection_open() {
    server_socketConnect();
    rs485_socketConnect();
}
function server_socketConnect() {
    server_connection = new WebSocket('ws://192.168.2.8:5000');
    server_connection.onopen = function () { serverOpened(); console.log('SERVER Connected!');};
    server_connection.onerror = function (error) { console.log('WebSocket Error ' + error); };
    server_connection.onmessage = function(e) { serverReceive(e.data); };
    server_connection.onclose = function(e) { serverClosed(); console.log('SERVER Disconnected!'); };
    ping_serverconnection=setInterval(function() {server_connection.send("ping");},5000);
}
function rs485_socketConnect() {
    rs485_connection = new WebSocket('ws://192.168.2.8:5001',"DomoProtocol");
    rs485_connection.onopen = function () { rs485Opened(); console.log('RS485 Connected!'); /*server_socketConnect()*/;};
    rs485_connection.onerror = function (error) { console.log('WebSocket Error ' + error); };
    rs485_connection.onmessage = function(e) { rs485Receive(e.data); };
    rs485_connection.onclose = function(e) { rs485Closed(); console.log('RS485 Disconnected!'); };
    //ping_rs485connection=setInterval(function() {rs485_connection.send("ping");},10000);
}
function socketConnection_close() {
    //clearInterval(ping_serverconnection);
    clearInterval(ping_rs485connection);
    //server_connection.send("exit");
    rs485_connection.send("exit");
    for(i=0;i<100000;i++);
    rs485_connection.close(); rs485_connection='';
    server_connection.close(); server_connection='';
}
function serverOpened() {
    document.getElementById("serverlightid").src=urlbase+"/images/icons/green.png";
}
function rs485Opened() {
    document.getElementById("rs485lightid").src=urlbase+"/images/icons/green.png";
}
function serverClosed() {
    server_connection.close(); server_connection='';
    document.getElementById("serverlightid").src=urlbase+"/images/icons/red.png";
    //server_socketConnect();
}
function rs485Closed() {
    rs485_connection.close(); rs485_connection='';    
    document.getElementById("rs485lightid").src=urlbase+"/images/icons/red.png";
}
function socketexpand() {
    if (sockethide) {
        document.getElementById("socketDivId").style.width="500px";
        document.getElementById("socketDivId").style.height="400px";
        document.getElementById("socketexpandid").style.display="none";
        document.getElementById("sockethideid").style.display="inline";
        sockethide=false;
    } else {
        document.getElementById("socketDivId").style.width="80px";
        document.getElementById("socketDivId").style.height="25px";
        document.getElementById("socketexpandid").style.display="inline";
        document.getElementById("sockethideid").style.display="none";
        sockethide=true;
    }
}

// *******************************************************************************************************
function serverReceive(msg) { alert("Dato Ricevuto server:"+msg); }

function server_connection_send(msg) {
    server_connection.send(msg);
    var node = document.createElement("span");
    var textnode = document.createTextNode(msg+" ");
    node.appendChild(textnode);
    document.getElementById("serversocketdivid").appendChild(node);
}

function rs485Receive(msg) {
    //var content=document.getElementById("rs485socketdivid");
    var node = document.createElement("span");
    var textnode = document.createTextNode(msg+" ");         
    node.appendChild(textnode);
    document.getElementById("rs485socketdivid").appendChild(node);     
    //alert("Dato Ricevuto 485:"+msg);
}
function rs485_connection_send(msg) {
    rs485_connection.send(msg);
    var node = document.createElement("span");
    var textnode = document.createTextNode(msg+" ");
    node.appendChild(textnode);
    document.getElementById("serversocketdivid").appendChild(node);
}

这是我在c:

中的服务器
#include<stdint.h>
#include<stdarg.h>
#include<stdio.h>
#include<math.h>
#include<string.h>    
#include<stdlib.h>    
#include<sys/socket.h>
#include<arpa/inet.h> 
#include<unistd.h>    
//for threading , link with lpthread
#include<pthread.h> 
//for SHA1 + BASE64
#include <openssl/sha.h>
const char *BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//for serial
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>

#define MAX_BUFFER 1000
#define DELAYTOSEND 1000000
#define MAX_CONNECTION 10
void *connection_handler(void *);
void *connection_handler_master(void *);
int serialBuffer[MAX_BUFFER];
long arg;


int main(int argc , char *argv[])
{
    int socket_desc , new_socket , c , *new_sock, i;
    struct sockaddr_in server , client;
    char client_message[2000], query[200]="";
    char *message, *token, *key;

    unsigned char obuf[20];
    unsigned char b64[100];

    //thread MASTER
    for(i=0;i<(MAX_BUFFER+1);i++) serialBuffer[i]=-1;
    pthread_t sniffer_thread;
    new_sock = malloc(1);
    *new_sock = new_socket;
     if( pthread_create( &sniffer_thread , NULL ,  connection_handler_master , (void*) new_sock) < 0) {
            perror("Non posso creare il Thread MASTER");
            return 1;
        }
    puts("Thread MASTER creato");

    //Create socket
    socket_desc = socket(AF_INET , SOCK_STREAM , 0);
    if (socket_desc == -1)     {
        printf("Impossibile creare un socket");
    }

    //Prepare the sockaddr_in structure
    server.sin_family = AF_INET;            //IPv4
    server.sin_addr.s_addr = INADDR_ANY;    
    server.sin_port = htons( 5001 );

    //Bind
    if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0) {
        puts("bind fallito");
        return 1;
    }
    puts("bind OK");

    //Listen
    listen(socket_desc , MAX_CONNECTION);

    //Accept and incoming connection
    puts("In attesa di connessione...");
    c = sizeof(struct sockaddr_in);


    while( (new_socket = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) ) {
        puts("Connessione accetata");
        recv(new_socket, client_message , 2000 , 0);
        token=strtok(client_message,"\r\n");
        //DEBUG while(token) { printf( "--------->:  %s\n", token ); token=strtok(NULL,"\r\n"); } printf("----------------------------------------\r\n");

        while(token != NULL) {
            if(!strncmp(token,"Sec-WebSocket-Key:",18)) break; //printf( "%s\n", token );
            token=strtok(NULL,"\r\n");
        }
        key=strtok(token," ");
        key=strtok(NULL," ");
        strcat(key,"258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
        SHA1(key,strlen(key),obuf);
        base64_encode(obuf,20,b64,100);

        printf( "KEY:  %s\n", key );
        printf( "B64:  %s\n", b64 );

        strcat(query,"HTTP/1.1 101 Switching Protocols\r\n");
        strcat(query,"Upgrade: Websocket\r\n");
        strcat(query,"Connection: Upgrade\r\n");
        strcat(query,"Sec-Websocket-Protocol:DomoProtocol\r\n");
        strcat(query,"Sec-WebSocket-Accept: ");
        strcat(query,b64);
        strcat(query,"\r\n\r\n");

        //DEBUG puts(token);        
        printf( "%s\n", query );
        write(new_socket , query , strlen(query));
        query[0]='\0';

        pthread_t sniffer_thread;
        new_sock = malloc(1);
        *new_sock = new_socket;

        if( pthread_create( &sniffer_thread , NULL ,  connection_handler , (void*) new_sock) < 0) {
            perror("Non posso creare il thread");
            return 1;
        }
        puts("Thread creato, Handler assegnato");
        printf("new_sock:%i\r\n",new_sock);
    }

    if (new_socket<0) {
        perror("Connessione rifiutata");
        return 1;
    }

    puts("uscita1");
    return 0;
}
/**
 * encode three bytes using base64 (RFC 3548)
 */
void _base64_encode_triple(unsigned char triple[3], char result[4])  {
    int tripleValue, i;
    tripleValue = triple[0];
    tripleValue *= 256;
    tripleValue += triple[1];
    tripleValue *= 256;
    tripleValue += triple[2];
    for (i=0; i<4; i++) { result[3-i] = BASE64_CHARS[tripleValue%64]; tripleValue /= 64; }
}
/**
 * encode an array of bytes using Base64 (RFC 3548)
 * return 1 on success, 0 otherwise
 */  
int base64_encode(unsigned char *source, size_t sourcelen, char *target, size_t targetlen) {
    if ((sourcelen+2)/3*4 > targetlen-1) return 0;

    /* encode all full triples */
    while (sourcelen >= 3) {
        _base64_encode_triple(source, target);
        sourcelen -= 3;
        source += 3;
        target += 4;
    }

    if (sourcelen > 0) {
        unsigned char temp[3];
        memset(temp, 0, sizeof(temp));
        memcpy(temp, source, sourcelen);
        _base64_encode_triple(temp, target);
        target[3] = '=';
        if (sourcelen == 1) target[2] = '=';
        target += 4;
    }

    target[0] = 0;
    return 1;
} 
/**
 * determine the value of a base64 encoding character
 * return the value in case of success (0-63), -1 on failure
 */  
int _base64_char_value(char base64char) {
    if (base64char >= 'A' && base64char <= 'Z')  return base64char-'A';
    if (base64char >= 'a' && base64char <= 'z')  return base64char-'a'+26;
    if (base64char >= '0' && base64char <= '9')  return base64char-'0'+2*26;
    if (base64char == '+')  return 2*26+10;
    if (base64char == '/')  return 2*26+11;
    return -1;
} 
/**
 * decode a 4 char base64 encoded byte triple
 * return lenth of the result (1, 2 or 3), 0 on failure
 */  
int _base64_decode_triple(char quadruple[4], unsigned char *result) {
    int i, triple_value, bytes_to_decode = 3, only_equals_yet = 1;
    int char_value[4];

    for (i=0; i<4; i++) char_value[i] = _base64_char_value(quadruple[i]);

    for (i=3; i>=0; i--) {
        if (char_value[i]<0) {
            if (only_equals_yet && quadruple[i]=='=') {
                char_value[i]=0;
                bytes_to_decode--;
                continue;
            }
        return 0;
        }
        only_equals_yet = 0;
    }

    if (bytes_to_decode < 0) bytes_to_decode = 0;

    triple_value = char_value[0];   triple_value *= 64;
    triple_value += char_value[1];  triple_value *= 64;
    triple_value += char_value[2];  triple_value *= 64;
    triple_value += char_value[3];

    for (i=bytes_to_decode; i<3; i++) triple_value /= 256;
    for (i=bytes_to_decode-1; i>=0; i--) { result[i] = triple_value%256; triple_value /= 256; }

    return bytes_to_decode;
} 
/**
 * decode base64 encoded data
 * return length of converted data on success, -1 otherwise
 */  
size_t base64_decode(char *source, unsigned char *target, size_t targetlen) {
    char *src, *tmpptr;
    char quadruple[4], tmpresult[3];
    int i, tmplen = 3;
    size_t converted = 0;

    src = (char *)malloc(strlen(source)+5);
    if (src == NULL) return -1;
    strcpy(src, source);
    strcat(src, "====");
    tmpptr = src;

    while (tmplen == 3) {
        for (i=0; i<4; i++) {
             while (*tmpptr != '=' && _base64_char_value(*tmpptr)<0) tmpptr++;
             quadruple[i] = *(tmpptr++);
        }
        tmplen = _base64_decode_triple(quadruple, tmpresult);
        if (targetlen < tmplen) { free(src); return -1; }
        memcpy(target, tmpresult, tmplen);
        target += tmplen;
        targetlen -= tmplen;
        converted += tmplen;
    }
    free(src);
    return converted;
}
/*
 * Serial Open
 */
int serialOpen (char *device, int baud) {
    struct termios options ;
    speed_t myBaud ;
    int     status, fd ;

    if ((fd = open (device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1) return -1 ;

    fcntl (fd, F_SETFL, O_RDWR) ;
    tcgetattr (fd, &options) ;
    cfmakeraw   (&options) ;
    cfsetispeed (&options, B115200) ;
    cfsetospeed (&options, B115200) ;
    options.c_cflag |= (CLOCAL | CREAD) ;
    options.c_cflag &= ~PARENB ;
    options.c_cflag &= ~CSTOPB ;
    options.c_cflag &= ~CSIZE ;
    options.c_cflag |= CS8 ;
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG) ;
    options.c_oflag &= ~OPOST ;
    options.c_cc [VMIN]  =   0 ;
    options.c_cc [VTIME] = 100 ;    // Ten seconds (100 deciseconds)

    tcsetattr (fd, TCSANOW | TCSAFLUSH, &options) ;
    ioctl (fd, TIOCMGET, &status);
    status |= TIOCM_DTR ;
    status |= TIOCM_RTS ;
    ioctl (fd, TIOCMSET, &status);
    usleep (10000) ;    // 10mS
    return fd ;
}
/*
 * DECODE / ENCODE STRING TO BINARY
 * */
char * decode( char *frame) {
    static char text[2000];
    int ofs=0, len=0, i=0, a=0;
    len = (int)(frame[1]) & 127;

    if (len == 126) { ofs = 8; }
        else if (len == 127) { ofs = 14; }
        else { ofs = 6; }
    text[0] = '\0';
    for (i = ofs; i < strlen(frame); i++) { text[a] = frame[i] ^ frame[ofs - 4 + (i - ofs) % 4]; a++; }
    text[a] = '\0';
    return text;
}
char * encode( char *frame) {
    int indexStartRawData=-1, i=0;
    long long int len=0;
    static char  bytesFormatted[2000];
    for(i=0;i<2000;i++) bytesFormatted[i]='\0';
    len = strlen(frame);
    bytesFormatted[0]= 129;
    if (len <= 125) {
        bytesFormatted[1] = len;
        indexStartRawData = 2;
    } else if (len >= 126 && len <= 65535) {
        bytesFormatted[1] = 126;
        bytesFormatted[2] = ( len >> 8 ) && 255;
        bytesFormatted[3] = ( len ) && 255;
        indexStartRawData = 4;
    } else {
        bytesFormatted[1] = 127;
        bytesFormatted[2] = ( len >> 56 ) && 255;
        bytesFormatted[3] = ( len >> 48 ) && 255;
        bytesFormatted[4] = ( len >> 40 ) && 255;
        bytesFormatted[5] = ( len >> 32 ) && 255;
        bytesFormatted[6] = ( len >> 24 ) && 255;
        bytesFormatted[7] = ( len >> 16 ) && 255;
        bytesFormatted[8] = ( len >>  8 ) && 255;
        bytesFormatted[9] = ( len ) && 255;
        indexStartRawData = 10;
    }
    strcat( bytesFormatted,frame);
    bytesFormatted[indexStartRawData+len] ='\0';
    return bytesFormatted;
}
char * asciiencode( int asciichar)  {
    int indexStartRawData=-1, i=0, len=0;
    static char bytesFormatted[10];
    static char asciiFormatted[10];
    for(i=0;i<=6;i++) bytesFormatted[i]='\0';

    sprintf(asciiFormatted,"%i\0",asciichar);
    len = strlen(asciiFormatted);
    bytesFormatted[0]= 129;
    bytesFormatted[1] = len;
    indexStartRawData = 2;

    strcat( bytesFormatted,asciiFormatted);
    bytesFormatted[indexStartRawData+len] =0;
    bytesFormatted[indexStartRawData+len+1] =0;
    bytesFormatted[indexStartRawData+len+2] ='\0';
    //bytesFormatted[indexStartRawData+len] ='\r';
    //bytesFormatted[indexStartRawData+len+1] ='\n';

    return bytesFormatted;
}

/*
 * Thread MASTER to popolate virtual array
 * */
void *connection_handler_master (void *socket_desc) {
     //Get the socket descriptor
    int sock = *(int*)socket_desc;
    int read_size;
    char *server_message , client_message[2000];
    int i=0;

    //Send some messages to the client
    server_message = "Creazione MASTER avvenuta. ";
    printf("%s\r\n",server_message);
    server_message = "In attesa di dati sul bus RS485.";
    printf("%s\r\n",server_message);
    int handle;
    uint8_t x ;
    handle = serialOpen ("/dev/ttyAMA0", 115200) ;
    //for(i=0;i<2001;i++) printf("%i: %i\r\n ",i,serialBuffer[i]);

    while(1) {
        while(!read (handle, &x, 1));
        if(x>-1) {
            serialBuffer[i]=x;
            //DEBUG printf("%i-%i\r\n",i,serialBuffer[i]);
            if(i==MAX_BUFFER) { serialBuffer[0]=-1; i=0; }
            else { serialBuffer[i+1]=-1; i++; }
        }
        x=-1;
    }

}
/*
 * Thread clients
 * */
void *connection_handler(void *socket_desc) {
    //Get the socket descriptor
    int sock = *(int*)socket_desc, read_size, i=0, a=0;
    char *server_message , client_message[2000], *c;


    //Send some messages to the client
    server_message = "Connessione avvenuta. ";
    write(sock , encode(server_message) , strlen(encode(server_message)));

    server_message = "In attesa di dati sul buffer.";
    write(sock , encode(server_message) , strlen(encode(server_message)));
    //DEBUG printf("sock:%i\r\n",sock);
    while(serialBuffer[i]!=-1) i++;

    while(1) {
        if(serialBuffer[i]!=-1) {
            //DEBUG printf("Serialdata%i: %i\r\n",i,serialBuffer[i]);
            server_message=asciiencode(serialBuffer[i]);
            write(sock , server_message , strlen(server_message));

            //printf("Serialdata--------------->%i: %s\r\n",i,server_message);

            if(i==MAX_BUFFER) i=0;
            else i++;
            for(a=0;a<DELAYTOSEND;a++) { }
        }

    }

    // This code is not used
    //Receive a message from client
    while( (read_size = recv(sock , client_message , 2000 , 0)) > 0 ) {
        //Received message from client
        //printf( "%s\n", decode(client_message) );

        //send message to client            
        //server_message="provina";
        //write(sock , encode(server_message) , strlen(encode(server_message)));
        printf( "%s\n",decode(client_message));
        //read (handle, &x, 1);
        //sprintf(c,"%i",x);
        //write (sock, encode(c),strlen(encode(c) ) );
        printf("serialBUffer: %s\r\n",serialBuffer);

    }

    if(read_size == 0)
    {
        puts("Client disconnected");
        fflush(stdout);
    }
    else if(read_size == -1)
    {
        puts("uscita2");
        perror("recv failed");
    }

    //Free the socket pointer
    puts("uscita3");
    free(socket_desc);

    return 0;
}

0 个答案:

没有答案