为什么增加一个线程可以使这个简单的套接字服务器更快?



这是我的服务器代码:

#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>rn";
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

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

主线程也是一个线程,所以即使你在现实中只调用一次pthread_create,你也有2个线程,主线程和你创建的线程,因此"1线程"和没有线程之间的区别。

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

最新更新