如果我真的很困惑,我对 C 很陌生,很抱歉。
我试图让一个服务器进程 fork() 另一个进程通过 popen() 运行 C 程序。但是,一旦我尝试读取字节,我的主服务器进程中的 accept() 就会收到错误消息。这是我得到错误的地方。
有人可以帮忙吗。
pipe_pointer = popen(cgi_command, "r");
if(pipe_pointer != NULL) {
while(!feof(pipe_pointer)) {
bytes_read = fread(buf, 1, sizeof(buf), pipe_pointer);
send(clientSock, buf, bytes_read, 0);
}
}
pclose(pipe_pointer);
这是整个代码
/**
* This method processes the first line of the HTTP request and stores it in the variable that the pointer
* buffer points to. In this case that variable is the request variable in the request_handler method. Returns 0 if nothing was received.
**/
int process_request(int clientSock, char *buffer) {
#define EOL "\r\n"
#define EOL_SIZE 2
char *bufferPointer = buffer;
int eol_matched = 0;
while(recv(clientSock, bufferPointer, 1, 0) != 0) {
if(*bufferPointer == EOL[eol_matched]) {
++eol_matched;
if(eol_matched == EOL_SIZE) {
*(bufferPointer+1-EOL_SIZE) = '\0';
return(strlen(buffer));
}
}
else {
eol_matched = 0;
}
bufferPointer++;
}
return(0);
}
int validate_get_request(char *buffer) {
char get_string[5] = "GET /";
if(strncasecmp(buffer, get_string, 5) != 0) {
return(-1);
}
else {
return(1);
}
}
/**
*This method takes a valid request and a pointer to a empty path variable, then fills out the path variable with the path of the requested file. Also it stores the requested filename in the filename variable
**/
void get_path(char *request, char *path, char *filename) {
char buf[1024];
int i = 0;
char *pointer = request;
pointer += 4;
while(!ISspace(pointer[i]) && pointer[i] != '\0') {
filename[i] = pointer[i];
i++;
}
filename[i] = '\0';
if(strcmp(filename, "/") == 0) {
strcpy(filename, "/index.html");
}
if(strstr(filename, ".cgi") != NULL) {
strcpy(path, CGIROOT);
}
else {
strcpy(path, DOCROOT);
}
strcat(path, filename);
}
void send_ok_header(int clientSock, char *mime) {
char buf[1024];
//Create OK Header, then add the file
strcpy(buf, "HTTP/1.0 200 OK\r\n");
send(clientSock, buf, strlen(buf), 0);
strcpy(buf, SERVER);
send(clientSock, buf, strlen(buf), 0);
strcpy(buf, "Content-Type: ");
send(clientSock, buf, strlen(buf), 0);
strcpy(buf, mime);
send(clientSock, buf, strlen(buf), 0);
strcpy(buf, "\r\n\r\n");
send(clientSock, buf, strlen(buf), 0);
}
void send_not_found(int clientSock, char *mime) {
char buf[1024];
//Create not found Header, then add the file
strcpy(buf, "HTTP/1.0 404 NOT FOUND\r\n");
send(clientSock, buf, strlen(buf), 0);
strcpy(buf, SERVER);
send(clientSock, buf, strlen(buf), 0);
strcpy(buf, "Content-Type: ");
send(clientSock, buf, strlen(buf), 0);
strcpy(buf, mime);
send(clientSock, buf, strlen(buf), 0);
strcpy(buf, "\r\n\r\n");
send(clientSock, buf, strlen(buf), 0);
strcpy(buf, "404 Sorry this webpage cannot be found\n");
send(clientSock, buf, strlen(buf), 0);
}
void send_unsupported(int clientSock, char *mime) {
char buf[1024];
//Create not found Header, then add the file
strcpy(buf, "HTTP/1.0 415 UNSUPPORTED MEDIA TYPE\r\n");
send(clientSock, buf, strlen(buf), 0);
strcpy(buf, SERVER);
send(clientSock, buf, strlen(buf), 0);
strcpy(buf, "Content-Type: ");
send(clientSock, buf, strlen(buf), 0);
strcpy(buf, mime);
send(clientSock, buf, strlen(buf), 0);
strcpy(buf, "\r\n\r\n");
send(clientSock, buf, strlen(buf), 0);
strcpy(buf, "415 Sorry this media type is not supported!!!\n");
send(clientSock, buf, strlen(buf), 0);
}
void send_unimplemented(int clientSock, char *mime) {
char buf[1024];
//Create not found Header, then add the file
strcpy(buf, "HTTP/1.0 501 UNIMPLEMENTED\r\n");
send(clientSock, buf, strlen(buf), 0);
strcpy(buf, SERVER);
send(clientSock, buf, strlen(buf), 0);
strcpy(buf, "Content-Type: ");
send(clientSock, buf, strlen(buf), 0);
strcpy(buf, mime);
send(clientSock, buf, strlen(buf), 0);
strcpy(buf, "\r\n\r\n");
send(clientSock, buf, strlen(buf), 0);
strcpy(buf, "501 Sorry this server only implements valid GET request\n");
send(clientSock, buf, strlen(buf), 0);
}
/**
This method takes the filename and fills the variable mime with its appropriate MIME type. Returns -1 if there is an unrecognized filename
**/
int get_mime_type(char *filename, char *mime, int *is_cgi) {
//WHY DOES THIS START WITH SOME WEIRD INITIAL VALUE ON THE 2ND TIME A REQUEST IS MADE?????
char extension[50] = "";
int return_val = -1;
char *pointer;
int filename_len = sizeof(filename);
int i = 0;
pointer = strstr(filename, ".");
if(pointer != NULL) {
while(pointer[i] != '\0') {
extension[i] = pointer[i];
i++;
}
}
if(strcasecmp(extension, ".html") == 0 || strcasecmp(extension, ".htm") == 0) {
strcpy(mime, "text/html");
return_val = 1;
}
else if(strcasecmp(extension, ".jpeg") == 0 || strcasecmp(extension, ".jpg") == 0) {
strcpy(mime, "image/jpeg");
return_val = 1;
}
else if(strcasecmp(extension, ".gif") == 0) {
strcpy(mime, "image/gif");
return_val = 1;
}
else if(strcasecmp(extension, ".txt") == 0) {
strcpy(mime, "text/plain");
return_val = 1;
}
//set the cgi variable to 1
else if(strcasecmp(extension, ".cgi") == 0) {
strcpy(mime, "text/html");
*is_cgi = 1;
return_val = 1;
}
return(return_val);
}
/**
* This is the function that the handler thread executes to handle each request
*/
void request_handler(int clientSock) {
FILE *pipe_pointer = NULL;
int i = 0;
int is_cgi = 0;
char buf[1024], path[1024], request[1024], mime[20], filename[50], *query_string[50] = {NULL}, *query_pointer, cgi_command[1024], cgibuf[1024];
long bytes_read;
//Send the actual html file with header
FILE *requestedfile = NULL;
//Take a request and fill it in the request variable
if(process_request(clientSock, request) != 0) {
//If it is a get request
if(validate_get_request(request) != -1) {
query_pointer = strtok(request, " ?=&");
strcpy(request, query_pointer);
while(query_pointer != NULL) {
query_string[i] = malloc(strlen(query_pointer) + 1);
strcpy(query_string[i], query_pointer);
query_pointer = strtok(NULL, " ?=&");
i++;
}
query_string[i] = NULL;
get_path(request, path, filename);
access(path, R_OK);
//if the file extension is unsupported throw a 415 code
if(get_mime_type(filename, mime, &is_cgi) != 1) {
send_unsupported(clientSock, mime);
}
else if(errno == ENOENT) { //filetype is recognized, but file cannot be found
send_not_found(clientSock, mime);
}
else if(errno == EACCES) { //filetype and file found, but no read access to the file
//fix this to a 403 error
perror("no access");
}
else { //PUT THE CGI code somewhere in this else statement
if(is_cgi == 1) {
i = 1;
//Create command to open cgi script
strcpy(cgi_command, "(cd ");
strcat(cgi_command, CGIROOT);
strcat(cgi_command, "; .");
strcat(cgi_command, filename);
strcat(cgi_command, " ");
while(query_string[2*i + 1] != NULL) {
strcat(cgi_command, query_string[2*i + 1]);
i++;
}
strcat(cgi_command, ")");
free(*query_string);
pipe_pointer = popen(cgi_command, "r");
if(pipe_pointer != NULL) {
while(!feof(pipe_pointer)) {
bytes_read = fread(cgibuf, 1, sizeof(cgibuf), pipe_pointer);
send(clientSock, cgibuf, bytes_read, 0);
}
}
pclose(pipe_pointer);
}
else {
//Open the file and start to send it
requestedfile = fopen(path, "rb");
//Send header
send_ok_header(clientSock, mime);
//Read the file by 1024 byte increments and send it
while(!feof(requestedfile)) {
bytes_read = fread(buf, 1, sizeof(buf), requestedfile);
send(clientSock, buf, bytes_read, 0);
}
}
}
}
else { //not a get request
send_unimplemented(clientSock, mime);
}
}
//Close the client socket when the request is fulfilled
//thread will die after this
close(clientSock);
}
int main(int argc, const char * argv[])
{
int server_sock_desc;
struct sockaddr_in name;
int client_sock_desc;
struct sockaddr_in client_name;
socklen_t addr_size;
pthread_t handler_thread;
//connection setup
server_sock_desc = socket(PF_INET, SOCK_STREAM, 0);
if(server_sock_desc != -1) {
memset(&name, 0, sizeof(name));
name.sin_family = AF_INET;
name.sin_port = htons(PORTNUMBER);
name.sin_addr.s_addr = htonl(INADDR_ANY);
int bind_result = bind(server_sock_desc, (struct sockaddr *) &name, sizeof(name));
if(bind_result == 0) {
if(listen(server_sock_desc, BACKLOG) < 0) {
perror("listen failed");
}
addr_size = sizeof(client_name);
//Server Loop will continue to run listening for clients connecting to the server
while(1) {
//new client attempting to connect to the server
client_sock_desc = accept(server_sock_desc, (struct sockaddr *) &client_name, &addr_size);
if(client_sock_desc == -1) {
perror("accept failed");
}
//connection starts here
//create a thread for the new clients request to be handled
if(pthread_create(&handler_thread, NULL, request_handler, client_sock_desc) != 0) {
perror("pthread_create failed");
}
}
}
else {
perror("bind failed");
}
}
else {
perror("socket failed");
}
}
fread() 执行后
程序执行立即跳转到这个循环并卡在第二行
while(recv(clientSock, bufferPointer, 1, 0) != 0) {
if(*bufferPointer == EOL[eol_matched]) {
++eol_matched;
if(eol_matched == EOL_SIZE) {
*(bufferPointer+1-EOL_SIZE) = '\0';
return(strlen(buffer));
}
}
else {
eol_matched = 0;
}
bufferPointer++;
}