为什么添加线程会使这个简单的套接字服务器更快?

时间:2013-04-03 15:55:55

标签: c performance sockets pthreads

这是我的服务器代码:

#include <stdio.h>
#include <arpa/inet.h>
#include <errno.h>
#include <sys/socket.h>
#include <pthread.h>

#define MY_PORT     843
#define MAXBUF      1028
#define NUM_THREADS     2

int pipes[1][2];
int sockfd;

const char *policy =
"<?xml version=\"1.0\"?>\n"
"<!DOCTYPE cross-domain-policy SYSTEM \"/xml/dtds/cross-domain-policy.dtd\">\n"
"<cross-domain-policy>\n"
"<site-control permitted-cross-domain-policies=\"master-only\"/>\n"
"<allow-access-from domain=\"*\" to-ports=\"*\" />\n</cross-domain-policy>\r\n";

void *SendPolicy(void *threadid) {
   int ok, clientfd;
   long tid;
   char buffer[MAXBUF];
   tid = (long) threadid;
   while(1) {
    /* --- Wait for, and recieve a client ---- */
    read(pipes[tid][0], &clientfd, sizeof(int), 0);

    /* --- Recieve --- */
    recv(clientfd, buffer, 128, 0);

    /* --- Send --- */
    send(clientfd, &policy, 250, 0);

    /* --- Close ---*/
    close(clientfd);
   }
}

int main(int argc, char *argv[]) {
    /* --- Create worker threads --- */
    pthread_t threads[NUM_THREADS];
    int t;
    for(t=0; t<NUM_THREADS; t++) {
        pipe(pipes[t]); // <- Create pipes for sending clients
        pthread_create(&threads[t], NULL, SendPolicy, (void *)t);
    }

    /* --- Create streaming socket --- */
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)  {
    perror("Socket");
    return 1;
    }

    /* --- Initialize address/port structure --- */
    struct sockaddr_in self;
    self.sin_family = AF_INET;
    self.sin_port = htons(MY_PORT);
    self.sin_addr.s_addr = INADDR_ANY;
    self.sin_family = AF_INET;

    /* --- Assign a port number to the socket --- */
    if (bind(sockfd, (struct sockaddr*) &self, sizeof(self)) != 0 ) {
    perror("Error: socket bind");
    return 1;
    }

    /* --- Make it a "listening socket" --- */
    if ( listen(sockfd, 20) != 0 )    {
    perror("socket--listen");
    return 1;
    }

    struct sockaddr_in client_addr;
    int addrlen=sizeof(client_addr);
    int clientfd;
    int current_thread = 0;
    while (1) {
        /* --- Accept a client --- */
    clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &addrlen);

    /* --- Send the client to a worker thread --- */
    write(pipes[current_thread][1], &clientfd, sizeof(int), 0);

    /* --- Cycle the threads --- */
    current_thread++;
    if (current_thread == NUM_THREADS)
        current_thread = 0;
    }

    /* --- Clean up --- */
    close(sockfd);
    pthread_exit(NULL);
    return 0;
}

最初,我写了这个计划使用5个线程,但我发现只有一个线程的最大收获。比任何线程都要多得多:

Concurrency Level:      1000
Time taken for tests:   12.607 seconds
Complete requests:      10000
Failed requests:        0
Write errors:           0
Total transferred:      2500000 bytes
HTML transferred:       0 bytes
Requests per second:    793.23 [#/sec] (mean)
Time per request:       1260.672 [ms] (mean)
Time per request:       1.261 [ms] (mean, across all concurrent requests)
Transfer rate:          193.66 [Kbytes/sec] received

这对我来说非常困惑,我不明白为什么只有一个线程可以比没有线程,或2,3,4,5个线程等更快。

1 个答案:

答案 0 :(得分:0)

主线程也是一个线程,所以即使你实际上只调用pthread_create一次你有2个线程,主线程和你创建的线程,因此“1线程”和没有线程之间的区别

至于2+个线程,你必须考虑拥有多个线程的开销,线程之间的切换通常比在进程之间切换便宜但不是零。