Concurrency 在代理中与malloc交互的线程?

Concurrency 在代理中与malloc交互的线程?,concurrency,proxy,thread-safety,malloc,semaphore,Concurrency,Proxy,Thread Safety,Malloc,Semaphore,我正在尝试将顺序代理转换为并发代理,其中多个线程可以处理来自Firefox等web浏览器的多个请求。现在,我一直在尝试使用信号量来确保代理线程的安全。我已经用gethostbyname\r替换了gethostbyname,从而解决了gethostbyname不具有线程安全性的问题。问题可能在我的mallocing中,因为我对这个概念还不熟悉。当我编译的时候,我要么免费得到一个无效点,要么得到一个人。我不知道我是否需要malloc我在parseuri部分已经做过的变量 #include "csap

我正在尝试将顺序代理转换为并发代理,其中多个线程可以处理来自Firefox等web浏览器的多个请求。现在,我一直在尝试使用信号量来确保代理线程的安全。我已经用gethostbyname\r替换了gethostbyname,从而解决了gethostbyname不具有线程安全性的问题。问题可能在我的mallocing中,因为我对这个概念还不熟悉。当我编译的时候,我要么免费得到一个无效点,要么得到一个人。我不知道我是否需要malloc我在parseuri部分已经做过的变量

#include "csapp.h"
#include <pthread.h>
#include <semaphore.h>

/* Globals */ 
FILE *log_file; /* Log file with one line per HTTP request */
sem_t mutex,maa, muu, mqq,mpp, mkk,mll;

typedef struct {
int clientfdpNum;
struct sockaddr_in *sockaddrT;
} thread_args;
 /* processRequest */
void processRequest(int proxyfd, struct sockaddr_in *sockaddr) {
P(&maa);
char fline[MAXLINE];
char rest[MAXLINE];
char method[MAXLINE], version[MAXLINE], uri[MAXLINE];
//P(&muu);
readLine(proxyfd, fline, MAXLINE); //reads firstline
read(proxyfd,rest, sizeof(rest)); //reads rest of request

//Read request line and headers 
sscanf(fline, "%s %s %s", method, uri, version);
//V(&muu);
//printf("\n%s\n",method);
//printf("URI %s\n",uri);
// printf("%s\n",version);
if (strcasecmp(method, "GET")) { 
clienterror(proxyfd, method, "501", "Not Implemented",
            "Proxy does not implement this method");
return;
}

//********************************Parse URI***********************************//

char *ip;
ip = (char*) Malloc(MAXLINE);
int newPort =80;
char *page;
page =  (char*) Malloc(MAXLINE);
char* slash;
slash = (char*) Malloc(MAXLINE);


sscanf(uri, "http://%99s[^:]:%99d/%99s[^\n]", ip, &newPort, page);
//printf("IP: %s\n",ip);
//printf("port: %d\n", newPort);
printf("page: %s\n", page);
page = strchr(ip,'/');
strcpy(slash,page);

char* colon = strchr(ip,':'); //find where colon is if port specified
if(colon != NULL){ //colon with new port is in ip
  colon++; //skip over colon
  newPort = atoi(colon); //convert to integer
  //printf("colon part: %s \n",colon);  
  colon--;
  *colon = '\0'; //terminate it earlier
} else{
int size = strlen(ip);
int size2 = strlen(page);
ip[size-size2]='\0';
}
V(&maa);
P(&mqq);
printf("\nnew IP: %s\n",ip);
printf("new port: %d\n", newPort);
printf("new page: %s\n", slash);



//*****************************Proxy acting as client***************************//
int clientfd;
struct hostent *hp;
struct sockaddr_in clientaddr;

if ((clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  return;
/*
// Fill in the server's IP address and port 
if ((hp = gethostbyname(ip)) == NULL){
  printf("Gethostbyname Problem\n");
  return; 
}
*/


 struct hostent hostbuf;
 size_t buflen;
char *bufh;
int res;
int herr;
buflen = 1024;
/* Allocate buffer, remember to free it to avoid memory leakage.  */
bufh = malloc (buflen);
while( (res = gethostbyname_r( ip, &hostbuf, bufh, buflen, &hp, &herr)) == ERANGE){
/* Enlarge the buffer.  */
buflen *= 2;
bufh = realloc(bufh, buflen);
if(bufh == NULL)
  perror("realloc");
}
/*  Check for errors.  */
if (res != 0 || hp == NULL){
  printf("threadsafe null\n");
  return;
}
free(bufh);



bzero((char *) &clientaddr, sizeof(clientaddr));
clientaddr.sin_family = AF_INET;
bcopy((char *)hp->h_addr_list[0], 
(char *)&clientaddr.sin_addr.s_addr, hp->h_length);
clientaddr.sin_port = htons(newPort);

// Establish a connection with the server
if (connect(clientfd, (SA *) &clientaddr, sizeof(clientaddr)) < 0)
return;
V(&mqq);
P(&mpp);
//*********************PRoxy acting as server back to browser****************//
char theRequest[MAXLINE] = {0};
sprintf(theRequest, "%s %s %s\r\n%s",method, slash, version, rest);
rio_writen(clientfd,theRequest,strlen(theRequest));

char buf[MAXLINE]={0};
int st,b;
int responseSize = 0;

do{
st = read( clientfd, buf, sizeof(buf) );
    //printf("%s", buf);
b = writenq(proxyfd, buf, st);
responseSize += b;
}while(st > 0);

//while(( r = recv(clientfd, buf, 1, 0))>0){
////rio_writen( proxyfd, webPAGE_buf, strlen(webPAGE_buf));
//printf("%s", buf);
//st = send( proxyfd, buf, strlen(buf), 0);
//}
close(clientfd);

//printf("Write Log\n");
//******************************WRITE LOG ***********************************//
char logstring[256];
//formats data aquired.
format_log_entry(logstring, sockaddr, ip, responseSize);
//writes to log
V(&mpp);

P(&mutex);  //Lock

fputs(logstring, log_file);
fflush(log_file);
free(ip);
free(slash);
free(page);

close(proxyfd);

V(&mutex); //Unlock
}

/* Thread routine */
void *thread(void *vargp){
  P(&mkk);
Pthread_detach(pthread_self());
thread_args *my_args = (thread_args *)vargp;
int clientfdp = my_args->clientfdpNum;
struct sockaddr_in *sockaddr = my_args->sockaddrT;

free(vargp);
V(&mkk);
//printf("process request in thread %d\n", clientfdp);
processRequest(clientfdp, sockaddr);

 return NULL;
}

/* main - Main routine for the proxy program*
int main(int argc, char **argv)
{
int sockfd, clientfdp, port;
struct sockaddr_in Clientaddr;
socklen_t clientlen = sizeof(Clientaddr);
pthread_t tid;
sem_init(&mutex, 0, 1);
sem_init(&muu, 0, 1);
sem_init(&maa, 0, 1);
sem_init(&mqq, 0, 1);
sem_init(&mpp, 0, 1);
sem_init(&mkk, 0, 1);
sem_init(&mll, 0, 1);

/* Check arguments */
if (argc != 2) {
  fprintf(stderr, "Usage: %s <port number>\n", argv[0]);
  exit(0);
}
signal(SIGPIPE, SIG_IGN);
//convert second Argument to integer
port = atoi(argv[1]);

//open log file
log_file = Fopen("Proxy.log","a");
if( log_file == NULL ){
puts ( "Cannot open Log file\n" );
exit(1);
 }

sockfd = open_listenfd(port);
//takes care of Socket, Bind, and Listen

while(1){
if((clientfdp = Accept(sockfd, (SA *)&Clientaddr, &clientlen)) < 0)
  err_exit();

thread_args *arguments = malloc(sizeof(thread_args));
arguments->clientfdpNum = clientfdp;
arguments->sockaddrT = &Clientaddr;
Pthread_create(&tid, NULL, thread, arguments);

//processRequest(clientfd, &Clientaddr); >> in thread
//close client fill descriptor
//close(clientfd);  >>in thread
}
exit(0);
}


void format_log_entry(char *logstring, struct sockaddr_in *sockaddr, char *uri, int size) {
time_t now;
char time_str[MAXLINE];
unsigned long host;
unsigned char a, b, c, d;

/* Get a formatted time string */
now = time(NULL);
strftime(time_str, MAXLINE, "%a %d %b %Y %H:%M:%S %Z", localtime(&now));
host = ntohl(sockaddr->sin_addr.s_addr);
a = host >> 24;
b = (host >> 16) & 0xff;
c = (host >> 8) & 0xff;
d = host & 0xff;
/* Return the formatted log entry string */
sprintf(logstring, "%s: %d.%d.%d.%d %s %d\n", time_str, a, b, c, d, uri, size);
}

char* readLine(int clientfd, char* line, int maxlen) {
// read one character at a time until we encounter \n
char c='a';
char* lineptr=line;
int nread=0;     
do {  
if(read(clientfd, &c, sizeof(c)) < 0) {
  if(errno==EINTR)
continue;
  err_exit();
}
nread++;
*lineptr++=c;    
} while(c != '\n' && nread<maxlen-1);

if(c=='\n')
  *(lineptr-1)=0; // overwrite \n if present
else
  *lineptr=0; // do not overwrite if different character
return line;
}

 /* writenq - writes and also handles SIGIN the signal interupt.  */
 size_t writenq(int fd, void *vptr, size_t n){
 size_t nleft;
size_t nwrite;
char *ptr;
ptr = vptr;
nleft = n;

while(nleft >0){
if((nwrite= write(fd, ptr, n)) <0){
  if(errno == EINTR)
nwrite=0;
  else 
return -1;
}
else if(nwrite ==0)
  break;

nleft -=nwrite;
ptr += nwrite;
}
return (n-nleft);
}
#包括“csapp.h”
#包括
#包括
/*全球*/
文件*日志文件;/*日志文件,每个HTTP请求一行*/
sem_t互斥体、maa、muu、mqq、mpp、mkk、mll;
类型定义结构{
int clientfdpNum;
*sockaddrT中的结构sockaddr_;
}线程参数;
/*处理请求*/
void processRequest(int proxyfd,结构sockaddr_in*sockaddr){
P&maa;
char-fline[MAXLINE];
charrest[MAXLINE];
char方法[MAXLINE],版本[MAXLINE],uri[MAXLINE];
//P&muu;
readLine(proxyfd、fline、MAXLINE);//读取第一行
read(proxyfd,rest,sizeof(rest));//读取请求的其余部分
//读取请求行和标题
sscanf(fline,“%s%s%s”,方法,uri,版本);
//V&muu;
//printf(“\n%s\n”,方法);
//printf(“URI%s\n”,URI);
//printf(“%s\n”,版本);
if(strcasecmp(方法,“GET”){
clienterror(proxyfd,方法“501”,“未实现”,
“代理未实现此方法”);
回来
}
//********************************解析URI***********************************//
字符*ip;
ip=(char*)Malloc(MAXLINE);
int newPort=80;
字符*页;
页面=(字符*)Malloc(最大行);
字符*斜杠;
斜杠=(char*)Malloc(MAXLINE);
sscanf(uri,“http://%99s[^:::%99d/%99s[^\n]”,ip,&newPort,第页);
//printf(“IP:%s\n”,IP);
//printf(“端口:%d\n”,新端口);
printf(“第页:%s\n”,第页);
page=strchr(ip,“/”);
strcpy(斜线,第页);
char*colon=strchr(ip,,:);//如果指定了端口,则查找冒号所在的位置
如果(冒号!=NULL){//带有新端口的冒号在ip中
冒号+++;//跳过冒号
newPort=atoi(冒号);//转换为整数
//printf(“冒号部分:%s\n”,冒号);
结肠--;
*冒号='\0';//提前终止它
}否则{
int size=strlen(ip);
int size2=strlen(第页);
ip[size-size2]='\0';
}
V&maa;
P&mqq;
printf(“\n新IP:%s\n”,IP);
printf(“新端口:%d\n”,新端口);
printf(“新页面:%s\n”,斜杠);
//*****************************代理作为客户***************************//
int clientfd;
结构主机*hp;
clientaddr中的结构sockaddr_;
if((clientfd=socket(AF_INET,SOCK_STREAM,0))<0)
回来
/*
//填写服务器的IP地址和端口
如果((hp=gethostbyname(ip))==NULL){
printf(“Gethostbyname问题”);
回来
}
*/
结构主机hostbuf;
布弗伦尺寸;
char*bufh;
国际关系;
先生;
buflen=1024;
/*分配缓冲区,记住释放它以避免内存泄漏*/
bufh=malloc(buflen);
while((res=gethostbyname_r(ip,&hostbuf,bufh,buflen,&hp,&herr))==ERANGE){
/*扩大缓冲区*/
buflen*=2;
bufh=realloc(bufh,buflen);
if(bufh==NULL)
perror(“realloc”);
}
/*检查错误*/
如果(res!=0 | | hp==NULL){
printf(“线程安全空\n”);
回来
}
免费(bufh);
bzero((char*)和clientaddr,sizeof(clientaddr));
clientaddr.sin_family=AF_INET;
b复制((char*)hp->h地址列表[0],
(char*)和clientaddr.sin_addr.s_addr,hp->h_长度);
clientaddr.sinu port=htons(newPort);
//与服务器建立连接
if(connect(clientfd,(SA*)和clientaddr,sizeof(clientaddr))<0)
回来
V&mqq;
P&mpp;
//*********************代理作为服务器返回到浏览器****************//
字符请求[MAXLINE]={0};
sprintf(请求,“%s%s%s\r\n%s”,方法,斜杠,版本,rest);
rio_writen(客户FD、theRequest、strlen(theRequest));
char buf[MAXLINE]={0};
int st,b;
int responseSize=0;
做{
st=读取(clientfd、buf、sizeof(buf));
//printf(“%s”,buf);
b=写入q(proxyfd、buf、st);
responseSize+=b;
}而(st>0);
//而((r=recv(clientfd,buf,1,0))>0){
////rio_writen(代理、网页、斯特伦(网页));
//printf(“%s”,buf);
//st=发送(proxyfd,buf,strlen(buf),0);
//}
关闭(clientfd);
//printf(“写入日志”);
//******************************写日志***********************************//
字符日志字符串[256];
//格式化获取的数据。
格式化日志条目(日志字符串、sockaddr、ip、responseSize);
//写入日志
V&mpp;
P(&mutex);//锁
FPUT(日志字符串、日志文件);
fflush(日志文件);
免费(ip);
自由(斜线);
免费(页);
关闭(proxyfd);
V(&mutex);//解锁
}
/*线程例程*/
void*螺纹(void*vargp){
P&mkk;
Pthread_detach(Pthread_self());
thread_args*my_args=(thread_args*)vargp;
int clientfdp=my_args->clientfdpNum;
结构sockaddr\u in*sockaddr=my\u args->sockaddrT;
免费(vargp);
V&mkk;
//printf(“线程%d中的进程请求”,clientfdp);
processRequest(clientfdp、sockaddr);
返回NULL;
}
/*main-代理程序的主例程*
int main(int argc,字符**argv)
{
int sockfd,clientfdp,端口;
Clientaddr中的结构sockaddr_;
socklen_t clientlen=sizeof(Clientaddr);
pthread_t tid;
sem_init(&mutex,0,1);
sem_init(&muu,0,1);
sem_-init(&maa,0,1);
sem_init(&mqq,0,1);
sem_init(&mpp,0,1);
sem_init(&mkk,0,1);
sem_init(&mll,0,1);
/*检查参数*/
如果(argc!=2){
fprintf(stderr,“用法:%s\n”,argv[0]);
出口(0);
}
信号(信号管、信号灯);
//将第二个参数转换为整数
端口=atoi(argv[1]);
//打开日志文件
log_file=Fopen(“Proxy.log”,“a”);
if(log_file==NULL){
puts(“无法打开日志文件\n”);
出口(1);
}
sockfd=打开_列表nfd(端口);
//负责套接字、绑定和侦听
而(1){
if((clientfdp=Accept(sockfd,(SA*)&Clientaddr,&clientlen))<0)
err_exit();
thread_args*参数=malloc(sizeof(thread_args));
参数->clientfdpNum=clientfdp;
参数->sockaddrT=&Clientaddr;
Pthread_创建(&tid,NULL,thread,arguments);
//processRequest(clientfd和ClientAddress);>>在线程中
//关闭客户端填充描述符