WEB客户与同时链接

client.cpp 文件
#include "unpthread.h"

#define MAXFILES 20
#define SERV "80"

struct file{
	char *f_name ; 
	char *f_host ; 
	int f_fd ; 
	int f_flags ;
	pthread_t f_tid ; 
}file[MAXFILES];

#define F_CONNECTING 1 
#define F_READING 2 
#define F_DONE 4

#define GET_CMD "GET %s HTTP/1.0\r\n\r\n"
#define F_JOINED 8 
int ndone ;
pthread_mutex_t ndone_mutex = PTHREAD_MUTEX_INITIALIZER ;
pthread_cond_t ndone_cond = PTHREAD_COND_INITIALIZER ;
int nconn , nfiles , nlefttoconn , nlefttoread ;

void *do_get_read(void *);
void home_page(const char * , const char *);
void write_get_cmd(struct file *);


/*主线程处理*/
int main(int argc , char **argv){
	int i , n , maxnconn ; 
	pthread_t tid ; 
	struct file *fptr ;
	if(argc < 5)
		throw runtime_error("usage : client <#conns> <IPaddr> <home_page> file1 ...");
	maxnconn = atoi(argv[1]);
	
	nfiles = min(argc -4 , MAXFILES) ;
	for( i = 0 ; i < nfiles ; i ++){
		file[i].f_name = argv[i + 4] ;
		file[i].f_host = argv[2] ;
		file[i].f_flags = 0 ; 
	}	

	cout << "nfiles = "<<nfiles <<endl;

	home_page(argv[2] , argv[3]);
	nlefttoconn = nlefttoread = nfiles ; 
	nconn = 0 ;


	while(nlefttoread > 0){
		while(nconn < maxnconn && nlefttoconn > 0){
			for( i = 0 ; i < nfiles ; i ++)
				if(file[i].f_flags == 0 )
					break;
			if( i == nfiles)
				throw runtime_error("nothing to connect");

			file[i].f_flags = F_CONNECTING ;
			pthread_create(&tid , NULL , &do_get_read , &file[i]);
			file[i].f_tid = tid ; 
			nconn ++ ;
			nlefttoconn -- ;
		}
	
		pthread_mutex_lock(&ndone_mutex);
		while(ndone == 0 )
			pthread_cond_wait(&ndone_cond , &ndone_mutex) ;

		for( i = 0 ; i < nfiles ; i++){
			if(file[i].f_flags & F_DONE){
				/*等待线程终止*/
				pthread_join(file[i].f_tid , (void **)&fptr);


				if(&file[i] != fptr )
					throw runtime_error("file[i] != fptr");
				fptr->f_flags = F_JOINED ;
				ndone -- ;
				nconn -- ;
				nlefttoread -- ;
				cout << "thread ID:  "<< fptr->f_tid << " name : " << fptr->f_name<<endl;
			}
		}
		pthread_mutex_unlock(&ndone_mutex);
	}
	return 0;
}

int Tcp_connect(const char * host , const char *serv){
	int fd , n ;
	struct addrinfo hints , *res , *ressave ;
	bzero(&hints , sizeof(hints));
	hints.ai_socktype = SOCK_STREAM ;
	hints.ai_family =  AF_UNSPEC ;

	if(getaddrinfo(host , serv , &hints , &res) != 0 )
		throw runtime_error("getaddrinfo error");
	ressave = res ;

	do{
		fd = socket(res->ai_family , res->ai_socktype ,res->ai_protocol);
		if(fd < 0 )
			continue ;
		if(connect(fd , res->ai_addr , res->ai_addrlen) == 0)
			break; //链接成功,跳出循环
		close(fd) ;
	}while( (res = res->ai_next)) ;

	if(res == NULL)
		throw runtime_error("scoket error");

	freeaddrinfo(ressave);
	return fd ; 
}

/*线程执行函数*/
void *do_get_read(void *vptr){
	int fd , n ;
	char line[MAXLINE] ;
	struct file *fptr ;
	fptr = (struct file *)vptr ;
	fd = Tcp_connect(fptr->f_host , SERV);
	fptr->f_fd = fd ;

	cout << "read " << fptr->f_name << "; fd : " << fptr->f_fd << "; thread ID :" << fptr->f_tid<<endl;

	write_get_cmd(fptr);

	while(true){
		if( (n = read(fd , line , MAXLINE) ) == 0)
			break;
		cout << "read " << n << " bytes from " << fptr->f_name<<endl;
	}
	cout << "end-of-file on " << fptr->f_name<<endl;
	close(fd);
	pthread_mutex_lock(&ndone_mutex);
	fptr->f_flags = F_DONE ;
	ndone ++ ;
	pthread_cond_signal(&ndone_cond);
	pthread_mutex_unlock(&ndone_mutex);
	return fptr ;
}

void home_page(const char *host , const char *fname ) {
	int fd , n ;
	char recv[MAXLINE] ;
	fd = Tcp_connect(host , SERV);

	n = snprintf(recv , sizeof(recv) , GET_CMD , fname);

	while(write(fd , recv , n ) == 0 )
		continue ;

	while(true){
		if( (n = read(fd , recv , MAXLINE )) == 0 )
			break;
		cout << "read " << n << " bytes from home_page. " <<endl;
	}
	cout << "end-of-home_page"<<endl;
	cout << "------------------------------------"<<endl;
	close(fd);
}

void write_get_cmd(struct file *fptr){
	int n ;
	char line[MAXLINE] ;

	n = snprintf(line , sizeof(line) , GET_CMD , fptr->f_name);
	while(write(fptr->f_fd , line , n ) == 0)
		continue ;

	cout << "wrote " << n << " from " << fptr->f_name<<endl;

	fptr->f_flags = F_READING ;
}

unp.h头文件
#include <pthread.h>
#include <iostream>
#include <exception>
#include <stdexcept>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/un.h>
#include <netdb.h>
#include <stdlib.h>
#include <cstdio>
#define MAXLINE 4096

using namespace std;





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值