【Linux网络编程-5】多线程服务端

//mthserver.cpp
#include "TcpServer.h"
#include "CLogFile.h"
#include <string>
#include <pthread.h>
#include <vector>

CLogFile logfile;
TcpServer tcpServer;
std::vector<long> vpthids;	//保存线程id

void mainEXIT(int sig)
{
    if(sig>0)	
    {
        signal(sig,SIG_IGN);
        signal(SIGINT,SIG_IGN);
        signal(SIGTERM,SIG_IGN);
        
        printf("mthserver exit..(PID=%d)\n",getpid());
        logfile.Write("mthserver exit..(PID=%d)\n",getpid());

        tcpServer.CloseListen();
        for(auto& pthid:vpthids)
        {
          pthread_cancel(pthid);
        }
        std::vector<long>(0).swap(vpthids);
        exit(0);
    }
}

void pthExit(void* arg)
{
    int sockfd=(int)(long)arg;
    close(sockfd);

    for(auto iter=vpthids.begin();iter!=vpthids.end();iter++)
    {
      if(*iter==pthread_self())
        vpthids.erase(iter);
    }

    logfile.Write("thread clean..\n") ;
}

bool biz002(const char* strRecvBuffer,char* strSendBuffer)
{
    char msg[1024];
    memset(msg,0,sizeof(msg));
    GetXmlBuffer(strRecvBuffer,"message",msg,1023);
    
    strcat(msg,"	ok");
    sprintf(strSendBuffer,"<retcode>0</retcode><message>%s</message>",msg);
    return true;
}


//业务1(business001)处理函数
bool biz001(const char* strRecvBuffer,char* strSendBuffer)
{
    //从strRecvBuffer中解析出username字段和password字段的值
    char username[51],password[51];
    memset(username,0,sizeof(username));
    memset(password,0,sizeof(password));
    
    GetXmlBuffer(strRecvBuffer,"username",username,50);
    GetXmlBuffer(strRecvBuffer,"password",password,50);
    
    //将用户名、密码同数据库中值对比
    if((strcmp(username, "wk")==0)&&(strcmp(password, "p@ssw0rd")==0))
        sprintf(strSendBuffer,"<retcode>0</retcode><message>login success</message>");
    else
        sprintf(strSendBuffer,"<retcode>-1</retcode><message>用户名或密码不正确</message>");
    
    return true;
}

//心跳响应
bool biz000(const char* strRecvBuffer,char* strSendBuffer)
{
    sprintf(strSendBuffer, "<retcode>0</retcode><message>heartbeat success</message>");
    return true;
}

//业务处理函数
//strRecvBuffer-接收报文
//strSendBuffer-发送报文
bool BusinessProcess(const char* strRecvBuffer,char* strSendBuffer)
{
    int ibizcode=-1;
    GetXmlBuffer(strRecvBuffer,"bizcode",&ibizcode);
    
    switch(ibizcode)
    {
        case 0:
            return biz000(strRecvBuffer,strSendBuffer);	//心跳
            break;
        case 1:
            return biz001(strRecvBuffer,strSendBuffer);	//登录
            break;
        case 2:
            return biz002(strRecvBuffer,strSendBuffer);	//业务2
            break;
        default:
            logfile.Write("非法报文:%s\n",strSendBuffer);
            return false;
    }
}

void* thmainfunc(void* arg)
{
    pthread_detach(pthread_self());
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
    pthread_cleanup_push(pthExit,arg);

    char strRecvBuffer[1024];
    char strSendBuffer[1024];
    int sockfd=(int)(long)arg;
    while(true)
    {
        memset(strRecvBuffer,0,sizeof(strRecvBuffer));
       	memset(strSendBuffer,0,sizeof(strSendBuffer));
        int iBufferlen;
        if(tcpServer.TcpRead(sockfd,strRecvBuffer, &iBufferlen,300)==false)  //超过60s没有收到心跳报文,就断开连接
            break;
        logfile.Write("recv msg:%s\n",strRecvBuffer);
        
        //业务处理
        if(BusinessProcess(strRecvBuffer,strSendBuffer)==false)
          pthread_exit(0);
        
       	logfile.Write("send msg:%s\n",strSendBuffer);
        if(tcpServer.TcpWrite(sockfd,strSendBuffer)==false)   
            break;
    }
    
    logfile.Write("client(%s) disconnected..\n", tcpServer.GetIP());
    pthread_cleanup_pop(1);
    pthread_exit(0);
}


int main(int argc, char** argv)
{
 	if(argc!=3)	
    {
        printf("Using: ./mthserver port logfile\nExample:./mthserver 5000 /tmp/mthserver.log\n\n");
        return -1;
    }
   
    for(int i=0;i<70;i++)
    {
        signal(i, SIG_IGN);
    }

    logfile.m_bBackup=false; //多进程服务程序关闭日志切换

    if(logfile.Open(argv[2], "a+") == false)	//a+添加,不存在则创建
    {
        printf("logfile open failed..(%s)\n", argv[2]);
    }
    
    signal(SIGINT,mainEXIT);	
    signal(SIGTERM,mainEXIT);
    if(tcpServer.InitServer(atoi(argv[1]))==false)
    {
        logfile.Write("server init failed..\n");
        mainEXIT(-1);
    }

    while(true)
    {
        if(tcpServer.Accept()==false)
        {
            logfile.Write("client(%s) connected failed..\n", tcpServer.GetIP());
            continue;	
        }
        logfile.Write("client(%s) connected..\n", tcpServer.GetIP());

        pthread_t pthid;
        if(pthread_create(&pthid,NULL,thmainfunc,(void*)(long)tcpServer.m_clientfd)!=0)
        {
          logfile.Write("create thread failed..\n");
          return -1;
        }
        vpthids.push_back(pthid);
    }
    return 0;
}
posted @ 2024-07-10 00:40  徘徊彼岸花  阅读(1)  评论(0编辑  收藏  举报