C中的Websocket实现

时间:2018-05-12 19:21:34

标签: c networking websocket

我是韩国学生。 我是用书面C编写Web服务器程序的。 我不知道为什么客户端(javascript)无法从服务器接收数据。 客户端(浏览器)也很好地连接到服务器。但是客户端无法从服务器接收数据。

我在Google上搜索过我的问题。但我找不到原因。搜索输出只是库的相关用法。 如果你有时间看,请查看我的代码

#define _WINSOCK_DEPRECATED_NO_WARNINGS 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include <process.h>
#include <sys/types.h>
#include <windows.h>
#include "dirent.h"


#define BUF_SIZE  2048
#define BUF_SMALL  100

unsigned  WINAPI RequestHandler(void* arg);
char* ContentType(char* file);
void SendData(SOCKET sock, char* ct, char* fileName);
void SendErrorMSG(SOCKET sock);
void ErrorHandling(char *message);
unsigned WINAPI updateFiles(void* arg);

typedef struct _clnt {
    SOCKET hClntSock;
    SOCKADDR_IN* clntAdr;
}Clnt, *LPClnt;

enum FLAG { SEND_TO_WEB, SEND_TO_CLIENT };

SOCKET hServSock;
SOCKADDR_IN servAdr;
int flag;


int main(int argc, char *argv[])
{
    WSADATA wsaData;
    SOCKET hClntSock;
    SOCKADDR_IN* clntAdr;
    LPClnt clnt;

    HANDLE hThread;
    DWORD dwThreadID;
    int clntAdrSize;

    if (argc != 2) {
        printf("Usage : %s <port>\n", argv[0]);
        exit(1);
    }

    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
        ErrorHandling("WSAStartup() error!");

    hServSock = socket(PF_INET, SOCK_STREAM, 0);
    memset(&servAdr, 0, sizeof(servAdr));
    servAdr.sin_family = AF_INET;
    servAdr.sin_addr.s_addr = htonl(INADDR_ANY);
    servAdr.sin_port = htons(atoi(argv[1]));

    if (bind(hServSock, (SOCKADDR*)&servAdr, sizeof(servAdr)) == SOCKET_ERROR)
        ErrorHandling("bind() error");
    if (listen(hServSock, 5) == SOCKET_ERROR)
        ErrorHandling("listen() error");


    /* 요청 및 응답 */
    while (1)
    {       
        clnt = (LPClnt)malloc(sizeof(Clnt));
        clntAdr = (SOCKADDR_IN*)malloc(sizeof(SOCKADDR_IN));
        clntAdrSize = sizeof(*clntAdr);
        hClntSock = accept(hServSock, (SOCKADDR*)clntAdr, &clntAdrSize);

        clnt->clntAdr = clntAdr;
        clnt->hClntSock = hClntSock;

        printf("Connection Request : %s:%d\n",
            inet_ntoa(clntAdr->sin_addr), ntohs(clntAdr->sin_port));
        printf("Socket Number : %d\n", clnt->hClntSock);

        hThread = (HANDLE)_beginthreadex(
            NULL, 0, RequestHandler, (void*)clnt, 0, (unsigned *)&dwThreadID);
    }
    closesocket(hServSock);
    WSACleanup();
    return 0;
}

unsigned WINAPI RequestHandler(void *arg)
{
    SOCKET hClntSock = ((LPClnt)arg)->hClntSock;
    SOCKADDR_IN* clntAdr = ((LPClnt)arg)->clntAdr;
    char buf[BUF_SIZE];
    char method[BUF_SMALL];
    char ct[BUF_SMALL];
    char fileName[BUF_SMALL];
    char* context;


    recv(hClntSock, buf, BUF_SIZE, 0);


    if (strstr(buf, "HTTP/") == NULL)    // HTTP에 의한 요청인지 확인
    {
        SendErrorMSG(hClntSock);
        closesocket(hClntSock);
        return 1;
    }
    else if (strstr(buf, "websocket")) {
        printf("WebSocket is connected\n");
        _beginthreadex(NULL, 0, updateFiles, (void*)hClntSock, 0, NULL);
        return 1;
    }

    strcpy_s(method, sizeof(method), strtok_s(buf, " /", &context));
    if (strcmp(method, "GET"))    // GET 방식 요청인지 확인 
        SendErrorMSG(hClntSock);

    strcpy_s(fileName, sizeof(fileName), strtok_s(NULL, " /", &context));    // 요청 파일이름 확인
    if(!strcmp(fileName, "HTTP"))  // index.html을 명시하지않앗다면
        strcpy_s(fileName, sizeof(fileName), "index.html");

    strcpy_s(ct, sizeof(ct), ContentType(fileName));    // Content-type 확인  
    SendData(hClntSock, ct, fileName);    // 응  답
    return 0;
}

void SendData(SOCKET sock, char* ct, char* fileName)
{
    char protocol[] = "HTTP/1.0 200 OK\r\n";
    char servName[] = "Server:simple web server\r\n";
    char cntLen[] = "Content-length:2048\r\n";
    char cntType[BUF_SMALL];
    char buf[BUF_SIZE];
    FILE* sendFile;

    sprintf_s(cntType, sizeof(cntType), "Content-type:%s; charset=UTF-8\r\n\r\n", ct);
    if (fopen_s(&sendFile, fileName, "r") != 0)
    {
        SendErrorMSG(sock);
        return;
    }

    /* 헤더 정보 전송 */
    send(sock, protocol, strlen(protocol), 0);
    send(sock, servName, strlen(servName), 0);
    send(sock, cntLen, strlen(cntLen), 0);
    send(sock, cntType, strlen(cntType), 0);

    /* 요청 데이터 전송 */
    while (fgets(buf, BUF_SIZE, sendFile) != NULL) {
        send(sock, buf, strlen(buf), 0);
    }

    closesocket(sock);   // HTTP 프로토콜에 의해서 응답 후 종료
}

void SendErrorMSG(SOCKET sock)   // 오류 발생시 메시지 전달
{
    char protocol[] = "HTTP/1.0 400 Bad Request\r\n";
    char servName[] = "Server:simple web server\r\n";
    char cntLen[] = "Content-length:2048\r\n";
    char cntType[] = "Content-type:text/html\r\n\r\n";
    char content[] = "<html><head><title>NETWORK</title></head>"
        "<body><p>오류 발생! 요청 파일명 및 요청 방식 확인!"
        "</p></body></html>";

    send(sock, protocol, strlen(protocol), 0);
    send(sock, servName, strlen(servName), 0);
    send(sock, cntLen, strlen(cntLen), 0);
    send(sock, cntType, strlen(cntType), 0);
    send(sock, content, strlen(content), 0);
    closesocket(sock);
}

char* ContentType(char* file)    // Content-Type 구분
{
    char extension[BUF_SMALL];
    char fileName[BUF_SMALL];
    char* context;

    strcpy_s(fileName, sizeof(fileName), file);
    strtok_s(fileName, ".", &context);
    strcpy_s(extension, sizeof(extension), strtok_s(NULL, ".", &context));
    if (!strcmp(extension, "html") || !strcmp(extension, "htm"))
        return "text/html";
    else
        return "text/plain";
}

unsigned WINAPI updateFiles(void* arg) {
    struct dirent* file;
    char* str;
    SOCKET webSock = (SOCKET)arg;
    DIR* dir;

    while (1) {
        dir = opendir(".");
        printf("to sent %d\n", webSock);
        while (file = readdir(dir)) {
            //printf("%s\n", file->d_name);
            send(webSock, 1, 1, 0);
        }
        Sleep(1000);
    }
}

void ErrorHandling(char* message)
{
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

&#13;
&#13;
<html>
<head>
    <meta charset="UTF-8">
    <title>NETWORK</title>
</head>
    <body>
        <ul id="list">
            <li>
                first11
            </li>
            <li>
                second
            </li>
        </ul>
    </body>

<script>
    const list = document.querySelector("#list");
    const sock = new WebSocket('ws://127.0.0.1:80');
    const arr = [];
    let li;

    sock.onmessage = evt => {
        console.log("ASD")
        li = document.createElement("li");
        if (arr.indexOf(evt.data) == -1) {
            arr.push(evt.data);
            li.innerHTML = evt.data;
            list.appendChild(li);
        }
    }
    
</script>
</html>
&#13;
&#13;
&#13;

这是我的输出。 如果我的程序没有问题,浏览器必须输出&#34; ASD&#34;,但什么都没有。

enter image description here

enter image description here

0 个答案:

没有答案