0
我試圖將一個順序代理轉換爲一個併發的代理,其中多個線程可以處理來自諸如Firefox等Web瀏覽器的多個請求。現在我被困在試圖使用信號量來使我的代理線程安全。通過用gethostbyname_r替換它,我已經處理了gethostby名稱不是線程安全的情況。這個問題可能出現在我的mallocing中,因爲我對這個概念還不熟悉。當我編譯時,我得到一個無效的點或一個男人。我不知道如果我甚至不需要malloc的,我做到了已經在PARSE URI部分線程與malloc在代理中干涉?
#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);
}
我需要做2個實施。一個使用線程,另一個分叉多個進程 – Krzysztof 2012-03-05 19:54:46
我明白這可能是一個更好的解決方案。顯示的代碼是我的線程實現 – Krzysztof 2012-03-05 20:04:40