深入理解计算机系统-----基于线程的服务器

1、实现代码

 #include "csapp.h"
 void echo(int connfd);
 void *thread(void *vargp);
int main(int argc, char **argv)
{
    int listenfd, connfd, port, clientl
    int *connfdp;
//  static pool pool;
    struct sockaddr_in clientaddr;
    struct hostent *hp;
    char *haddrp;
    pthread_t tid;
    fd_set read_set,ready_set;
    if (argc != 2)
    {
        fprintf(stderr, "usage: %s <port>\n", argv[0]);
        exit(0);
    }
    port = atoi(argv[1]);
    // Signal(SIGCHLD,sigchld_handler);
    listenfd = Open_listenfd(port);
    while (1)
     {
 
         clientlen=sizeof(struct sockaddr_in);
         connfdp=Malloc(sizeof(int));
         *connfdp=Accept(listenfd,(SA*)&clientaddr,&clientlen);
         Pthread_create(&tid,NULL,thread,connfdp);
     }
 
 }
 
 void *thread(void *vargp)
 {
     int connfd=*((int *)vargp);
     Pthread_detach(pthread_self());
     Free(vargp);
     echo(connfd);
     Close(connfd);
     return NULL;
 }                              

2、代码分析

        基于线程的并发echo服务器代码整体结构类似于基于进程的设计。主线程不断等待连接请求,然后创建一个对等线程处理该请求。有一个值得注意的问题就是,调用pthread_create函数时,如何将已连接描述符传递给对等线程,最明显的方法就是传递一个指向这个描述符的指针,就像下面这样:

插入一下创建线程的函数原型,这样就能理解这个描述符是怎么样传递的了。

#include <pthread.h>
//第一个参数为指向线程标识符的指针。
//第二个参数用来设置线程属性。
//第三个参数是线程运行函数的起始地址。
//最后一个参数是运行函数的参数。
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                          void *(*start_routine) (void *), void *arg);

然后在对等线程中间接引用这个指针,并将它赋值给一个局部变量。

然而这样会出错,因为在对等线程的赋值语句和主线程的accept语句之间引入了竞争。如果赋值语句在下一个accept函数之前完成,那么对等线程的局部变量connfd会得到正确地描述符。但是如果赋值语句在accept函数之后才完成,那么对等线程中的局部变量connfd就得到下一次连接的描述符。导致的结果就是,两个线程在同一个描述符上执行输入和输出,为了避免这个问题,必须将accept函数返回的每个已连接描述符分配到他自己的动态分配的内存块,像例程代码while(1)里面一样。另一个问题就是在线程例程中避免内存泄漏,既然不显式地回收线程,就必须分离每个线程(Pthread_detach(pthread_self());),使得它终止时内存资源能被收回。更进一步我们应该释放主线程分配地内存块(也就是accept返回值分配的内存块, Free(vargp);)。

3、结果

        有一个需要注意的地方是,:pthread不是Linux下的默认的库,也就是在链接的时候,无法找到phread库中哥函数的入口地址,于是链接会失败。在这时需要在编译时添加选项-lpthread。可以如下图:

验证如下:

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值