码迷,mamicode.com
首页 > 其他好文 > 详细

unix网络编程各种TCP客户-服务器程序设计实例(二)

时间:2015-07-12 11:22:11      阅读:140      评论:0      收藏:0      [点我收藏+]

标签:java   unix   

本节我们接着介绍另外的几种TCP客户-服务器程序;

第四种:TCP并发服务器,每个客户一个子线程

在我们前面的并发服务器程序例子中可以看出:父进程接受连接,派生子进程,子进程处理与客户的交互。

这种模式的问题:

fork()是昂贵的。内存映像要从父进程拷贝到子进程,所有描述字要在子进程中复制等等。

fork()子进程后,需要用进程间通信在父子进程之间传递信息。

一个进程中的所有线程共享相同的全局内存,这使得线程很容易共享信息,但是这种简易型也带来了同步问题。一个进程中的所有线程不仅共享全局变量,而且共享:

进程指令,大多数数据,打开的文件(如描述字),信号处理程序和信号处置,当前工作目录,用户ID和组ID;

所以我们才引进了线程;

技术分享

当一个程序由exec启动时,会创建一个称作初始线程或主线程的单个线程。额外线程则由pthread_create函数创建。

一个进程中的每个线程都由一个线程ID标识,其数据类型是pthread_t(常常是unsigned int)。如果新的线程创建成功,其ID将通过tid指针返回。

每个线程都有很多属性:优先级、起始栈大小、是否应该是一个守护线程,等等。当创建线程时我们可以通过初始化一个phread_attr_t变量说明这些属性以覆盖缺省值。

最后,当创建一个线程时,我们要说明一个它将执行的函数。线程以调用该函数开始,然后或者显示地终止(调用pthread_exit)或者隐式的终止(让函数返回)。参数时以个指针arg。

我们可以调用pthread_join等待一个线程终止。类似于waitpid。

我们必须指定要等待线程的tid。不能等待任意一个线程结束(类似于waitpid的进程ID参数为-1的情况)。

 

互斥锁:

多个线程修改一个共享变量,是最简单的问题,解决方法是用一个互斥锁(mutex)保护共享变量;只有我们持有互斥锁才能访问该变量。

技术分享

互斥锁是类型为pthread_mutex_t的变量。

条件变量:

互斥锁适于阻止对共享变量的同时访问,但是我们需要某种东西以使我们能够睡眠等待某种条件出现。我们需要一种方法使得主循环进入睡眠,直到有一个线程通知它某件事已就绪。条件变量加上互斥锁可以提供这种功能。互斥锁提供互斥机制,条件变量提供信号机制。

条件变量是一个pthread_cond_t类型的变量。

技术分享

多线程客户端程序:

 

技术分享

  1. #include "unpthread.h"  
  2. void* copyto(void*);  
  3. static int sockfd;//全局变量,所有线程共有  
  4. static FILE *fp;  
  5. void str_cli1(FILE *fp_arg, int sockfd_arg){  
  6.     char recvline[MAXLINE];  
  7.     pthread_t tid;  
  8.     sockfd = sockfd_arg;  
  9.     fp = fp_arg;  
  10.     Pthread_create(&tid,NULL,copyto,NULL);  
  11.     while(Readline(sockfd,recvline,MAXLINE)>0)  
  12.         Fputs(recvline,stdout);  
  13. }  
  14.   
  15. void* copyto(void* arg){  
  16.    char sendline[MAXLINE];  
  17.    while(Fgets(sendline,MAXLINE,fp)!=NULL)  
  18.         Writen(sockfd,sendline,strlen(sendline));  
  19.    Shutdown(sockfd,SHUT_WR);  
  20.    return(NULL);  
  21. }  
  22.   
  23. int  
  24. main(int argc, char **argv)  
  25. {  
  26.     int sockfd;  
  27.     struct sockaddr_in  servaddr;  
  28.   
  29.     if (argc != 2)  
  30.         err_quit("usage: tcpcli <IPaddress>");  
  31.   
  32.     sockfd = Socket(AF_INET, SOCK_STREAM, 0);  
  33.   
  34.     bzero(&servaddr, sizeof(servaddr));  
  35.     servaddr.sin_family = AF_INET;  
  36.     servaddr.sin_port = htons(SERV_PORT);  
  37.     Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);  
  38.   
  39.     Connect(sockfd, (SA *) &servaddr, sizeof(servaddr));  
  40.   
  41.     str_cli1(stdin, sockfd);        /* do it all */  
  42.   
  43.     exit(0);  
  44. }  

服务器程序:

  1. #include    "unpthread.h"  
  2. static void *doit(void *);      /* each thread executes this function */  
  3.   
  4. int  
  5. main(int argc, char **argv)  
  6. {  
  7.     int             listenfd, connfd;  
  8.     pthread_t       tid;  
  9.     socklen_t       addrlen, len;  
  10.     struct sockaddr *cliaddr;  
  11.   
  12.     if (argc == 2)  
  13.         listenfd = Tcp_listen(NULL, argv[1], &addrlen);  
  14.     else if (argc == 3)  
  15.         listenfd = Tcp_listen(argv[1], argv[2], &addrlen);  
  16.     else  
  17.         err_quit("usage: tcpserv01 [ <host> ] <service or port>");  
  18.   
  19.     cliaddr = Malloc(addrlen);  
  20.   
  21.     for ( ; ; ) {  
  22.         len = addrlen;  
  23.         connfd = Accept(listenfd, cliaddr, &len);  
  24.         Pthread_create(&tid, NULL, &doit, (void *) connfd);  
  25.     }  
  26. }  
  27.   
  28. static void *  
  29. doit(void *arg)  
  30. {  
  31.     Pthread_detach(pthread_self());  
  32.     str_echo((int) arg);    /* same function as before */  
  33.     Close((int) arg);       /* done with connected socket */  
  34.     return(NULL);  
  35. }  


注意:这里我们编译的时候,由于pthread不是系统默认的库,所以要用命令:

gcc tcpcli.c -o client -lunp -lpthread

gcc tcpserv.c -o server -lunp -lpthread

服务器运行命令:sudo ./server 127.0.0.1 9877

客户端运行命令:./client 127.0.0.1

我们注意到每种客户端的程序其实只要是str_cli函数的改变,main函数没有变化;

好了,又介绍完了一种设计实例,明天继续,未完待续。。。


版权声明:本文为博主http://www.zuiniusn.com原创文章,未经博主允许不得转载。

unix网络编程各种TCP客户-服务器程序设计实例(二)

标签:java   unix   

原文地址:http://blog.csdn.net/u013948191/article/details/46848481

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!