zoukankan      html  css  js  c++  java
  • socket编程之并发回射服务器3

    socket编程之并发回射服务器一文中,服务器采用多进程的方式实现并发,本文采用多线程的方式实现并发。

    多线程相关API:

    // Compile and link with -pthread
    int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                              void *(*start_routine) (void *), void *arg);
    int pthread_join(pthread_t thread, void **retval);
    
    int pthread_detach(pthread_t thread);

    pthread_join类似waitpid,用于等待一个线程的结束。

    pthread_detach将线程状态变成detachable。

    一个detachable线程终止后,它的资源自动释放回系统,不需要其他线程join。

    具体代码如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <signal.h>
    #include <sys/wait.h>
    #include <sys/errno.h>
    #include <pthread.h>
    
    #define MAXLINE 4096
    #define LISTENQ 10
    #define PORT 8888
    
    void doEcho(int sockfd) {
        char buff[MAXLINE];
        while (true) {
            memset(buff, 0, sizeof(buff));
            int n = read(sockfd, buff, MAXLINE);
            if (n < 0) {
                perror("read error");
                exit(1);
            } else if (n == 0) {
                printf("client closed
    ");
                break;
            }
            fputs(buff, stdout);
            write(sockfd, buff, n);
        }
    }
    
    static void* doit(void *arg) {
        int sockfd = *(int*)arg;
        free(arg);
        
        pthread_detach(pthread_self());
        doEcho(sockfd);
        close(sockfd);
        return (NULL);
    }
    
    int main(int argc, char **argv) {
        
        int listenfd, connfd;
        pthread_t tid;
        socklen_t clilen;
        struct sockaddr_in servaddr, cliaddr;
        
        if ( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
            perror("socket error");
            exit(1);
        }
        
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port = htons(PORT);
        
        if ( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {
            perror("bind error");
            exit(1);
        }
        
        if ( listen(listenfd, LISTENQ) < 0) {
            perror("listen error");
            exit(1);
        }
        
        for ( ; ; ) {
            clilen = sizeof(cliaddr);
            if ( (connfd = accept(listenfd, (struct sockaddr*)&cliaddr, &clilen)) < 0) {
                if (errno == EINTR) {
                    continue;
                } else {
                    perror("accept error");
                    exit(1);
                }
            }
            
            int *pconnfd = (int*)malloc(sizeof(int));
            *pconnfd = connfd;
            pthread_create(&tid, NULL, &doit, pconnfd);
        }
    }
    View Code

     需要注意的是给新线程传递参数的方法,不能直接传递connfd。

  • 相关阅读:
    python多线程多进程
    python单元测试unittest
    python学习笔记(一):python简介和入门
    今天的收获!!!
    Python django
    React router
    30分钟掌握ES6/ES2015核心内容
    webpack+React.js
    我喜欢的两个js类实现方式 现在再加上一个 极简主义法
    js实现的笛卡尔乘积-商品发布
  • 原文地址:https://www.cnblogs.com/gattaca/p/6415632.html
Copyright © 2011-2022 走看看