#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>/* struct hostent,gethostbynameのため */
#include <fcntl.h>
#include <sys/stat.h>
#define Err(x) {fprintf(stderr,"error ");perror(x);exit(0);}
#define print_ip(a) {printf("%d.%d.%d.%d\n",(0x0ff&(a>>24)),(0x0ff&(a>>16)),(0x0ff&(a>>8)),(0x0ff&a));}
int server_fd;/* ソケット識別子 */
char hostname[256];
struct hostent *phost;
struct in_addr **addrptr;/* IPアドレス配列のポインタ管理用 */
struct sockaddr_in server_adr;
int client_fd;
struct sockaddr_in client_adr;
struct stat sbuf;
main(){
int yes=1;
/* ソケットの生成 */
server_fd=socket(AF_INET, SOCK_STREAM, 0);
if(server_fd < 0) Err("socket");
/* サーバホスト名取得 */
printf("socket handle:%u\n",server_fd);
if(gethostname(hostname,sizeof(hostname)) < 0) Err("gethostname");
printf("host name:%s\n", hostname);
/* ホスト名からID取得 */
phost = gethostbyname(hostname);
if(phost == NULL)Err("gethostbyname");
int n = 0;
while(phost->h_addr_list[n] != NULL){
addrptr=(struct in_addr **)phost->h_addr_list;
printf("%s\n", inet_ntoa(*addrptr[n]));
n++;
}
/* setsockopt(server_fd,
SOL_SOCKET, SO_REUSEADDR, (const char *)&yes, sizeof(yes));
*/
/* ソケットへの割り当て */
memset((char *) &server_adr, sizeof(server_adr),0);
server_adr.sin_family = AF_INET;
server_adr.sin_port = htons(8888);
server_adr.sin_addr = *addrptr[0];
server_adr.sin_addr.s_addr = inet_addr("192.168.253.3");
if(bind(server_fd, (struct sockaddr *)&server_adr, sizeof(server_adr)) < 0) Err("bind");
if(listen(server_fd, 5) == -1) Err("listen");
while(1){
int status;
int len = sizeof(client_adr);
client_fd = accept(server_fd,(struct sockaddr*)&client_adr, &len);
if(client_fd < 0) Err("accept");
if(fork()==0) client_proc();
close(client_fd);
wait(&status);
}
}
int client_proc(){
char buf[12048];
char path[256]=".";
int pathlen;
int numb = 0;
int len = 0;
int bin_flag = 1;
int n;
while(len < sizeof(buf)){
n = recv(client_fd, buf+len, 1, 0);
if(n < 0) break;
//printf("%d", len);
//putchar(buf[len]);
if(buf[len++]!=0x0a){
continue;
}
buf[len]='\0';
fputs(buf,stdout);
if(buf[1]==0x0a && len==2) break;
len=0;
numb++;
if(numb == 1){
char *s = strchr(buf, '/');
if(s != NULL) strcpy(path+1,s);
s = strchr(path, ' ');
if(s != NULL) *s = '\0';
}
}
pathlen=strlen(path);
if(pathlen>5){
if(strcmp(path+pathlen-5,".html") == 0) bin_flag=0;
if(strcmp(path+pathlen-4,".htm") == 0) bin_flag=0;
if(strcmp(path+pathlen-4,".txt") == 0) bin_flag=0;
}
if(strcmp(path,"./")==0 || stat(path,&sbuf) < 0){
sprintf(buf,"HTTP/1.0 404 Not Found\r\n\r\n");
printf("%s",buf);
if(send(client_fd,buf,strlen(buf),0) < 0) Err("not found send");
} else {
FILE *fp=fopen(path,"r");
int c;
if(fp==NULL)Err("fopen");
printf("file path===%d=====%s===%dbyte\n",bin_flag,path, sbuf.st_size);
len = sprintf(buf,"HTTP/1.0 200 OK\r\n");
len += sprintf(buf+len,"Server: suzuki test/1.0\r\n");
len += sprintf(buf+len,"Accept-Ranges: bytes\r\n");
len += sprintf(buf+len,"Content-Length: %d\r\n",sbuf.st_size);
if(bin_flag==1){
len += sprintf(buf+len,"Content-Type: application/octet-stream\r\n");
} else {
len += sprintf(buf+len,"Content-Type: text/html\r\n");
}
len += sprintf(buf+len,"\r\n");
printf("%s",buf);
if(send(client_fd,buf,len,0) < 0) Err("not found send");
len=0;
while((c=fgetc(fp)) != EOF){
buf[len++]=c;
}
printf("%dbyte\n",len);
fclose(fp);
if(send(client_fd,buf,len,0) < 0) Err("send html");
}
if( shutdown(client_fd, 2) < 0) Err("shutdown");
close(client_fd);
exit(0);
}