国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

基于多反應(yīng)堆的高并發(fā)服務(wù)器【C/C++/Reactor】(中)在TcpConnection 中接收并解析Http請(qǐng)求消息

這篇具有很好參考價(jià)值的文章主要介紹了基于多反應(yīng)堆的高并發(fā)服務(wù)器【C/C++/Reactor】(中)在TcpConnection 中接收并解析Http請(qǐng)求消息。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

一、在TcpConnection 中多添加和http協(xié)議相關(guān)的request和response

struct TcpConnection {
    struct EventLoop* evLoop;
    struct Channel* channel;
    struct Buffer* readBuf;
    struct Buffer* writeBuf;
    char name[32];
    // http協(xié)議
    struct HttpRequest* request;
    struct HttpResponse* response;
};

二、給客戶端回復(fù)數(shù)據(jù)(方法一)

1.在Buffer.h文件中添加bufferSendData函數(shù):

// 發(fā)送數(shù)據(jù)
int bufferSendData(struct Buffer* buf,int socket);
// 發(fā)送數(shù)據(jù)
int bufferSendData(struct Buffer* buf,int socket) {
    // 判斷有無(wú)數(shù)據(jù)
    int readableSize = bufferReadableSize(buf);// 這些未讀的數(shù)據(jù)就是待發(fā)送的數(shù)據(jù)
    if(readableSize > 0) {
        int count = send(socket,buf->data + buf->readPos,readableSize,MSG_NOSIGNAL);
        if(count > 0) {
            buf->readPos += count;
            usleep(1);
        }
        return count;
    }    
    return 0;
}

?2.在TcpConnection.c文件中添加processWrite函數(shù):

int processWrite(void* arg) {
    struct TcpConnection* conn = (struct TcpConnection*)arg;
    // 發(fā)送數(shù)據(jù)
    int count = bufferSendData(conn->writeBuf,conn->channel->fd);
    if(count > 0) {
        // 判斷數(shù)據(jù)是否被全部發(fā)送出去了
        if(bufferReadableSize(conn->writeBuf) == 0){
            // 1.不再檢測(cè)寫事件 -- 修改channel中保存的事件
            writeEventEnable(conn->channel,false);
            // 2.修改dispatcher檢測(cè)的集合 -- 添加任務(wù)節(jié)點(diǎn)
            eventLoopAddTask(conn->evLoop,conn->channel,MODIFY);    
            // 3.刪除這個(gè)節(jié)點(diǎn)
            eventLoopAddTask(conn->evLoop,conn->channel,DELETE);
        }
    }
    return 0;
}

3.修改tcpConnectionInit函數(shù)中調(diào)用的channelInit函數(shù)的寫回調(diào)函數(shù)為processWrite函數(shù)

?// 初始化
struct TcpConnection* tcpConnectionInit(int fd,struct EventLoop* evLoop) {
    struct TcpConnection* conn = (struct TcpConnection*)malloc(sizeof(struct TcpConnection));
    conn->evLoop = evLoop;
    struct Channel* channel = channelInit(fd,ReadEvent,processRead,processWrite,tcpConnectionDestroy,conn);
    conn->channel = channel;
    conn->readBuf = bufferInit(10240); // 10k
    conn->writeBuf = bufferInit(10240); // 10k
    sprintf(conn->name,"TcpConnection-%d",fd);

    // http協(xié)議
    conn->request = httpRequestInit();
    conn->response = httpResponseInit();

    // 把channel添加到事件循環(huán)對(duì)應(yīng)的任務(wù)隊(duì)列里邊
    eventLoopAddTask(evLoop,conn->channel,ADD);
    return conn;
}

三、給客戶端回復(fù)數(shù)據(jù)(方法二)

  • 在TcpConnection.h中添加?
// #define MSG_SEND_AUTO
  • TcpConnection.c
// 接收客戶端數(shù)據(jù)
int processRead(void* arg) {
    struct TcpConnection* conn = (struct TcpConnection*)arg;
    // 接收數(shù)據(jù)
    int count = bufferSocketRead(conn->readBuf,conn->channel->fd);
    if(count > 0) {
        // 接收到了Http請(qǐng)求,解析Http請(qǐng)求
        int socket = conn->channel->fd;
#ifdef MSG_SEND_AUTO  // 給客戶端回復(fù)數(shù)據(jù)的方式一
        writeEventEnable(conn->channel,true);
        eventLoopAddTask(conn->evLoop,conn->channel,MODIFY);
#endif
        bool flag = parseHttpRequest(conn->request,conn->readBuf,conn->response,conn->writeBuf,socket);
        if(!flag) {
            // 解析失敗,回復(fù)一個(gè)簡(jiǎn)單的html
            char* errMsg = "Http/1.1 400 Bad Request\r\n\r\n";
            bufferAppendString(conn->writeBuf,errMsg);
        }
    }
    else{
#ifdef MSG_SEND_AUTO
        // 斷開連接
        eventLoopAddTask(conn->evLoop,conn->channel,DELETE);
#endif
    }
#ifndef MSG_SEND_AUTO
    // 斷開連接
    eventLoopAddTask(conn->evLoop,conn->channel,DELETE);
#endif
    return 0;
}

1.修改HttpRequest.c文件中的sendFile函數(shù)和sendDir函數(shù)

void sendFile(const char* fileName,struct Buffer* sendBuf,int cfd) {
    // 打開文件
    int fd = open(fileName,O_RDONLY);
    if(fd < 0) {
        perror("open");
        return;
    }
    // assert(fd > 0); 
#if 1
    while (1) {
        char buf[1024];
        int len = read(fd,buf,sizeof(buf));
        if(len > 0) {
            // send(cfd,buf,len,0);
            bufferAppendData(sendBuf,buf,len);
#ifndef MSG_SEND_AUTO // 給客戶端回復(fù)數(shù)據(jù)(方法二)
            bufferSendData(sendBuf,cfd);
#endif
        }
        else if(len == 0) {
            break;
        }
        else{
            close(fd);
            perror("read");
        }
    }
#else
    // 把文件內(nèi)容發(fā)送給客戶端
    off_t offset = 0;
    int size = lseek(fd,0,SEEK_END);// 文件指針移動(dòng)到了尾部
    lseek(fd,0,SEEK_SET);// 移動(dòng)到文件頭部
    while (offset < size){
        int ret = sendfile(cfd,fd,&offset,size - offset);
        printf("ret value: %d\n",ret);
        if (ret == -1 && errno == EAGAIN) {
            printf("沒數(shù)據(jù)...\n");
        }
    }
#endif
    close(fd);
}

void sendDir(const char* dirName,struct Buffer* sendBuf,int cfd) {
    char buf[4096] = {0};
    sprintf(buf,"<html><head><title>%s</title></head><body><table>",dirName);
    struct dirent** nameList;
    int num = scandir(dirName,&nameList,NULL,alphasort);
    for(int i=0;i<num;i++) {
        // 取出文件名 nameList 指向的是一個(gè)指針數(shù)組 struct dirent* tmp[]
        char* name = nameList[i]->d_name;
        struct stat st;
        char subPath[1024] = {0};
        sprintf(subPath,"%s/%s",dirName,name);
        stat(subPath,&st);
        if(S_ISDIR(st.st_mode)) {
            // 從當(dāng)前目錄跳到子目錄里邊,/
            sprintf(buf+strlen(buf),
                "<tr><td><a href=\"%s/\">%s</a></td><td>%ld</td></tr>",
                name,name,st.st_size);
        }else{
            sprintf(buf+strlen(buf),
                "<tr><td><a href=\"%s\">%s</a></td><td>%ld</td></tr>",
                name,name,st.st_size);
        }
        // send(cfd,buf,strlen(buf),0);
        bufferAppendString(sendBuf,buf);
#ifndef MSG_SEND_AUTO // 給客戶端回復(fù)數(shù)據(jù)(方法二)
        bufferSendData(sendBuf,cfd);
#endif
        memset(buf,0,sizeof(buf));
        free(nameList[i]); 
    } 
    sprintf(buf,"</table></body></html>");
    // send(cfd,buf,strlen(buf),0);
    bufferAppendString(sendBuf,buf);
#ifndef MSG_SEND_AUTO // 給客戶端回復(fù)數(shù)據(jù)(方法二)
    bufferSendData(sendBuf,cfd);
#endif
    free(nameList);
}
 

2.修改HttpResponse.c文件的httpResponsePrepareMsg函數(shù)

// 組織http響應(yīng)數(shù)據(jù)
void httpResponsePrepareMsg(struct HttpResponse* response,struct Buffer* sendBuf,int socket) {
    // 狀態(tài)行
    char tmp[1024] = {0};
    sprintf(tmp,"HTTP/1.1 %d %s\r\n",response->statusCode,response->statusMsg);
    bufferAppendString(sendBuf,tmp);
    
    // 響應(yīng)頭
    for(int i=0;i<response->headerNum;++i) {
        // memset(tmp,0,sizeof(tmp));  ?????????
        sprintf(tmp,"%s: %s\r\n",response->headers[i].key,response->headers[i].value);
        bufferAppendString(sendBuf,tmp);
    }

    // 空行
    bufferAppendString(sendBuf,"\r\n");
    
#ifndef MSG_SEND_AUTO // 給客戶端回復(fù)數(shù)據(jù)(方法二)
    bufferSendData(sendBuf,socket);
#endif
    // 回復(fù)的數(shù)據(jù)
    response->sendDataFunc(response->fileName,sendBuf,socket);
}

?四、釋放資源 tcpConnectionDestroy

基于多反應(yīng)堆的高并發(fā)服務(wù)器【C/C++/Reactor】(中)在TcpConnection 中接收并解析Http請(qǐng)求消息,高并發(fā)服務(wù)器,C/C++/Reactor,基于多反應(yīng)堆的

// 釋放資源
int tcpConnectionDestroy(void* arg);
// 釋放資源
int tcpConnectionDestroy(void* arg) {
    struct TcpConnection* conn = (struct TcpConnection*)arg;
    if(conn!=NULL) {
        if (conn->readBuf && bufferReadableSize(conn->readBuf) == 0 &&
            conn->writeBuf && bufferReadableSize(conn->writeBuf) == 0) {
            destroyChannel(conn->evLoop,conn->channel);
            bufferDestroy(conn->readBuf);
            bufferDestroy(conn->writeBuf);
            httpRequestDestroy(conn->request);
            httpResponseDestroy(conn->response);
            free(conn);
        }
    }
    return 0;
}

五、日志功能

#pragma once
#include <stdarg.h>
#include <stdio.h>

#define  DEBUG   1  

#if DEBUG
/*
*  如果不加 do ... while(0) 在進(jìn)行條件判斷的時(shí)候(只有一句話), 省略了{(lán)}, 就會(huì)出現(xiàn)語(yǔ)法錯(cuò)誤
*  if 
*     xxxxx
*  else
*     xxxxx
*  宏被替換之后, 在 else 前面會(huì)出現(xiàn)一個(gè) ;  --> 語(yǔ)法錯(cuò)誤
*/
#define LOG(type, fmt, args...)  \
  do{\
    printf("%s: %s@%s, line: %d\n***LogInfo[", type, __FILE__, __FUNCTION__, __LINE__);\
    printf(fmt, ##args);\
    printf("]\n\n");\
  }while(0)
#define Debug(fmt, args...) LOG("DEBUG", fmt, ##args)
#define Error(fmt, args...) do{LOG("ERROR", fmt, ##args);exit(0);}while(0)
#else
#define LOG(fmt, args...)  
#define Debug(fmt, args...)
#define Error(fmt, args...)
#endif


?文章來源地址http://www.zghlxwxcb.cn/news/detail-818744.html

到了這里,關(guān)于基于多反應(yīng)堆的高并發(fā)服務(wù)器【C/C++/Reactor】(中)在TcpConnection 中接收并解析Http請(qǐng)求消息的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包