實現基於windows的多執行緒Web伺服器端
阿新 • • 發佈:2019-01-25
程式碼來源於《TCP/IP網路程式設計》(尹聖雨著)第24章--製作HTTP伺服器端。
純C語言實現:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <winsock2.h> #include <process.h> #define BUF_SIZE 2048 #define BUF_SMALL 100 unsigned WINAPI RequestHandler(void *arg); char* ComtentType(char *file); void SendData(SOCKET sock, char* ct, char* filename); void SendErrorMSG(SOCKET sock); void ErrorHandling(char *message); int main(int argc, char *argv[]) { WSADATA wsaData; SOCKET hServSock,hClntSock; SOCKADDR_IN servAdr, clntAdr; HANDLE hThread; DWORD dwThreadID; int clntAdrSize; if(argc!=2){ printf("Usage : %s< port >\n",argv[0]); exit(1); } if( WSAStartup( MAKEWORD(2,2), &wsaData )!=0 ) ErrorHandling( "WSAStartup() error!" ); hServSock=socket(PF_INET, SOCK_STREAM , 0); memset( &servAdr, 0 ,sizeof(servAdr) ); servAdr.sin_family = AF_INET; servAdr.sin_addr.s_addr = htonl(INADDR_ANY); servAdr.sin_port = htons(atoi(argv[1])); if(bind(hServSock,(SOCKADDR *)&servAdr, sizeof(servAdr)) == SOCKET_ERROR) ErrorHandling( "bind() error!" ); if(listen(hServSock,5)== SOCKET_ERROR) ErrorHandling( "listen() error!" ); while(1) { clntAdrSize = sizeof( clntAdr ); hClntSock = accept( hServSock,(SOCKADDR *)&clntAdr, &clntAdrSize ); printf("Connection Request : %s:%d\n",inet_ntoa(clntAdr.sin_addr),ntohs(clntAdr.sin_port)); hThread = (HANDLE)_beginthreadex( NULL,0,RequestHandler,(void*)hClntSock,0,(unsigned *)&dwThreadID); } closesocket(hServSock); WSACleanup(); return 0; } unsigned WINAPI RequestHandler(void *arg) { SOCKET hClntSock= (SOCKET)arg; char buf[BUF_SIZE]; char method[BUF_SMALL]; char ct[BUF_SMALL]; char filename[BUF_SMALL]; recv(hClntSock,buf,BUF_SIZE,0); if(strstr(buf,"HTTP/")==NULL) { SendErrorMSG(hClntSock); closesocket(hClntSock); return 1; } strcpy(method,strtok(buf," /")); if( strcmp( method,"GET" ) ) SendErrorMSG(hClntSock); strcpy( filename,strtok(NULL," /") ); strcpy(ct,ComtentType(filename)); SendData(hClntSock, ct, filename); return 0; } char* ComtentType(char *file) { char extension[BUF_SMALL]; char fileName[BUF_SMALL]; strcpy(fileName,file); strtok(fileName,"."); strcpy(extension,strtok(NULL,".")); if(!strcmp(extension,"html")|| !strcmp(extension,"htm")) return "text/html"; else return "text/plain"; } void SendData(SOCKET sock, char* ct, char* filename) { char protocol[] = "HTTP/1.0 200 OK\r\n"; char servName[] = "Server:simple web server\r\n"; char cntLen[] = "Content-length:2048\r\n"; char cntType[BUF_SIZE]; char buf[BUF_SIZE]; FILE * sendFile; sprintf(cntType,"Content-type:%s\r\n\r",ct); if((sendFile=fopen(filename,"r"))==NULL) { SendErrorMSG(sock); return; } send(sock, protocol, strlen(protocol),0); send(sock, servName, strlen(servName),0); send(sock, cntLen, strlen(cntLen),0); send(sock, cntType, strlen(cntType),0); while(fgets(buf,BUF_SIZE,sendFile)!=NULL) send(sock,buf,strlen(buf),0); closesocket(sock); } void SendErrorMSG(SOCKET sock) { char protocol[] = "HTTP/1.0 400 Bad Request\r\n"; char servName[] = "Server:simple web server\r\n"; char cntLen[] = "Content-length:2048\r\n"; char cntType[] = "Content-type:text/html\r\n\r"; char content[] = "<html><head><title>NETWORK</title></head>" "<body><font size=+5><br> 發生錯誤!" "</font></body></html>"; send(sock, protocol, strlen(protocol),0); send(sock, servName, strlen(servName),0); send(sock, cntLen, strlen(cntLen),0); send(sock, cntType, strlen(cntType),0); send(sock, content,strlen(content),0); closesocket(sock); } void ErrorHandling(char *message) { fputs(message,stderr); fputc('\n',stderr); exit(1); }
嗯,從書上敲了一遍,最後成功執行,還是碰到點問題。總結一下:
1.需要準備一個index.html的檔案放在exe同路徑下,index.html儘量簡單,沒有語法錯誤
2.執行該exe需要一個附帶的引數--埠號。書中例子以9190為埠號
4.特備註意瀏覽器只能用IE瀏覽器。(我也不知道為什麼其他瀏覽器訪問不了,可能是安全性太低了,如果大佬知道,希望指教一下)
5.exe所在路徑最好不要有中文,或者名字太長,或者有一些奇怪的符號,否則可能讀不到html.index檔案
再貼一下我自己寫的index.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>點選那個按鈕</title> </head> <head> </head> <body> <button id="myBtn">點選一下就好了</button> <script> document.getElementById("myBtn").onclick=function(){successTouch()}; var movex; var movey; var elem=document.getElementById("myBtn"); elem.style.width = "100px"; elem.style.height = "60px"; function changeBtnPos(){ elem.style.position = "absolute"; w=Math.random()*window.innerWidth-elem.offsetWidth; h=Math.random()*window.innerHeight-elem.offsetHeight; if (w<=0) { w=0; } if (h<=0) { h=0; } elem.style.left = w+"px"; elem.style.top = h+"1px"; if(Math.random()>0.5){ document.getElementById("myBtn").innerHTML="點選不到吧"; }else{ document.getElementById("myBtn").innerHTML="點選呀"; } } document.getElementById("myBtn").onmousemove = changeBtnPos function whichButton(event) { if(event.button==1) { document.getElementById("myBtn").onmousemove=function(){} } } function successTouch() { alert("你成功了!"); document.getElementById("myBtn").onmousemove = changeBtnPos } document.onmousedown=whichButton </script> </body> </html>