最近在读《UNIX网络编程》,但是只读书而不实践是远远不行的。在阅读完线程池那块之后,自己动手写了一个简单的基于线程池的server/client程序。程序如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<pthread.h>
int clifd[32];
#define thread_num 10
#define MAXLINE 16384
static int iput = 0;
static int iget = 0;
pthread_mutex_t clifd_mutex;
pthread_cond_t new_conn = PTHREAD_COND_INITIALIZER;
void child_serv(int sock_fd){
char buf[MAXLINE];
int nread;
int nwrite;
while((nread=read(sock_fd,buf,MAXLINE))>0){
nwrite = write(sock_fd,buf,nread);
printf("server write %d bytes to client\n",nwrite);
}
if(nread<0)
printf("read error\n");
}
void * thread_func(){
int connfd;
while(1){
pthread_mutex_lock(&clifd_mutex);
while(iget==iput)
pthread_cond_wait(&new_conn,&clifd_mutex);
connfd=clifd[iget];
iget++;
pthread_mutex_unlock(&clifd_mutex);
child_serv(connfd);
close(connfd);
}
}
int main(int argc, char ** argv){
int listen_fd,conn_fd;
socklen_t client_len;
pthread_t thread_id[thread_num];
int i=0;
struct sockaddr_in serv_addr,client_addr;
for(i=0;i<thread_num;i++){
pthread_create(&thread_id[i],NULL,&thread_func,NULL);
}
if((listen_fd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==-1){
printf("socket create error: %s\n",strerror(errno));
exit(0);
}
memset(&serv_addr,0,sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(6666);
if(bind(listen_fd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))==-1){
printf("bind error: %s\n",strerror(errno));
exit(0);
}
if(listen(listen_fd,10)==-1){
printf("listen error: %s\n",strerror(errno));
exit(0);
}
while(1){
conn_fd = accept(listen_fd,NULL,NULL);
pthread_mutex_lock(&clifd_mutex);
clifd[iput] = conn_fd;
iput++;
pthread_cond_signal(&new_conn);
pthread_mutex_unlock(&clifd_mutex);
}
return 0;
}
server端在启动进程的时候会创建10个线程,这10个线程就构成了线程池。
当连接数组clifd为空的时候,这些线程就会睡眠。当有新的连接到来后,主线程会发送信号到条件变量信号,这时候在线程池中就会有线程被唤醒,该线程即可去处理客户的请求。
client端的程序如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<pthread.h>
#define MAXLINE 4096
void str_cli(FILE * fp,int sock_fd){
char sendline[MAXLINE],recvline[MAXLINE];
while(fgets(sendline,MAXLINE,fp)!=NULL){
write(sock_fd,sendline,strlen(sendline));
if(read(sock_fd,recvline,MAXLINE)==0)
printf("read error\n");
fputs(recvline,stdout);
}
}
int main(int argc, char ** argv){
int sock_fd;
struct sockaddr_in serv_addr;
char recvline[4096], sendline[4096];
if((sock_fd = socket(AF_INET,SOCK_STREAM,0))<0){
printf("create socket error: %s\n",strerror(errno));
exit(0);
}
memset(&serv_addr,0,sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(6666);
if(inet_pton(AF_INET,argv[1],&serv_addr.sin_addr,sizeof(serv_addr))<0){
printf("inet_pton error: %s\n",strerror(errno));
exit(0);
}
if(connect(sock_fd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))<0){
printf("connect error: %s\n",strerror(errno));
exit(0);
}
str_cli(stdin,sock_fd);
return 0;
}