使用select进行进行处理

这次博主在上一次的基础上,进行了升级,上个版本是使用单个线程处理,当并发量比较高的时候,比较慢,今天博主进行了升级,使用多线程,当客户端发送请求的时候,当检测到文件描述符符合条件时就会开一个子线程去处理,然后当客户端发送处理时,也会开一个线程,但是最后也别忘记了线程同步,避免数据竞争导致数据混乱,这样可以大大提高速度。

下面是改进后的代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include
#include
pthread_mutex_t mutex;
typedef struct fdinfo
{
        int fd;
        int *maxfd;
        fd_set* redset;
}FDInfo;
void* acceptConn(void *arg){
        std::cout<<"pd_id: "<fd, NULL, NULL);
        pthread_mutex_lock(&mutex);
            if (cfd == -1) {
                std::cout << "accept error" << std::endl;
                exit(1);
            }
            std::cout << "New client connected: " << std::endl;
            FD_SET(cfd, info->redset);
            *info->maxfd=std::max(cfd,*info->maxfd);
        pthread_mutex_unlock(&mutex);
            free(info);
            return NULL;
}
void *communication(void *arg){
         std::cout<<"pd_id:"<fd, buf, sizeof(buf), 0);
                if (len == -1) {
                    std::cout << "recv error" << std::endl;
                    exit(1);
                    free(info);
                    return NULL;
                } else if (len == 0) {
                   pthread_mutex_lock(&mutex);
                    FD_CLR(info->fd, info->redset);
                    close(info->fd);
                    pthread_mutex_unlock(&mutex);
                    std::cout << "client is closed" << std::endl;
                    free(info);
                    return NULL;
                }
                                // 转换为大写
                for (int j = 0; j < len; j++) {
                    buf[j] = toupper(buf[j]);
                    std::cout << "alter buf: " << buf[j] << std::endl;
                }
              int ret = send(info->fd, buf, strlen(buf) + 1, 0);
                if (ret == -1) {
                    std::cout << "send error" << std::endl;
                    free(info);
                    return NULL;
                }
                free(info);
                return NULL;

}
int main(int argc, const char* argv[]) {
        pthread_mutex_init(&mutex,NULL);
    int lfd = socket(AF_INET, SOCK_STREAM, 0); // 创建监听套接字
    if (lfd == -1) {
        std::cout << "socket error" << std::endl;
        exit(0);
    }

    struct sockaddr_in ser_addr;
    memset(&ser_addr, 0, sizeof(ser_addr));
    ser_addr.sin_family = AF_INET;
    ser_addr.sin_port = htons(8888);
    ser_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    // 绑定端口
    int ret = bind(lfd, (struct sockaddr*)&ser_addr, sizeof(ser_addr));
    if (ret == -1) {
        std::cout << "bind error" << std::endl;
        exit(1);
    }

    // 监听
    ret = listen(lfd, 64);
    if (ret == -1) {
        std::cout << "listen error" << std::endl;
        exit(1);
    }

    fd_set redset;
    FD_ZERO(&redset);
    FD_SET(lfd, &redset);
    int maxfd = lfd;
   while (1) {
        pthread_mutex_lock(&mutex);
        fd_set tmp = redset;
        int ret = select(maxfd + 1, &tmp, NULL, NULL, NULL);
         pthread_mutex_unlock(&mutex);
        // 处理监听套接字
        if (FD_ISSET(lfd, &tmp)) {

            pthread_t tid;
            FDInfo* info= new FDInfo();
            info->fd=lfd;
            info->maxfd = &maxfd;
            info->redset=&redset;
            pthread_create(&tid,NULL,acceptConn,info);
            pthread_detach(tid);
        }
        // 处理客户端套接字
        for (int i = 0; i <= maxfd; i++) {
            if (i != lfd && FD_ISSET(i, &tmp)) {
                pthread_t tid;
                FDInfo* info= new FDInfo();
                info->fd=i;
                info->redset=&redset;
                pthread_create(&tid,NULL,communication,info);
                pthread_detach(tid);
            }
        }
    }
    pthread_mutex_destroy(&mutex);
    close(lfd);
    return 0;
}
                                                                                                                                                                                                                                                                                                                                                       下面是运行结果,客户端会发送一个json文件,他会全部转化为大写返回

博主发送了密码和账号:

可以看到全部转化为大写并发送回去,开了大概8个线程。

今天的更新就到这了。下次见