[关闭]
@1405010312 2016-12-02T04:13:39.000000Z 字数 3553 阅读 495

web服务器

web服务器


1.http协议

  • 其响应客户端的请求后就立马断开连接,也就是说服务端不会维持客户端状态.所以其又称为"无状态的Stateless协议"由于这个特性,web编程通常用Cookie和Session技术.

  • 请求消息结构:其由消息行,消息头,消息体构成.请求行含有请求方式信息(GET和POST),请求行只有一行.消息头包含发送请求的浏览器信息,用户认证信息等附加信息.消息体与消息头中有一行空行用来区分消息头和消息体.

2.实验原理

  • 获取请求消息,并相应提取请求方式和文件的绝对路径,通过绝对路径打开文件,然后传送给浏览器.

3.实验代码

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <winsock2.h>
  5. #include <process.h>
  6. #define BUF_SIZE 2048
  7. #define BUF_SMALL 100
  8. unsigned WINAPI RequestHandler(void* arg);
  9. char* ContentType(char* file);
  10. void SendData(SOCKET sock, char* ct, char* fileName);
  11. void SendErrorMSG(SOCKET sock);
  12. void ErrorHandling(char *message);
  13. int main(int argc, char *argv[])
  14. {
  15. WSADATA wsaData;
  16. SOCKET hServSock, hClntSock;
  17. SOCKADDR_IN servAdr, clntAdr;
  18. HANDLE hThread;
  19. DWORD dwThreadID;
  20. int clntAdrSize;
  21. if(argc!=2) {
  22. printf("Usage : %s <port>\n", argv[0]);
  23. exit(1);
  24. }
  25. if(WSAStartup(MAKEWORD(2, 2), &wsaData)!=0)
  26. ErrorHandling("WSAStartup() error!");
  27. hServSock=socket(PF_INET, SOCK_STREAM, 0);
  28. memset(&servAdr, 0, sizeof(servAdr));
  29. servAdr.sin_family=AF_INET;
  30. servAdr.sin_addr.s_addr=htonl(INADDR_ANY);
  31. servAdr.sin_port=htons(atoi(argv[1]));
  32. if(bind(hServSock, (SOCKADDR*) &servAdr, sizeof(servAdr))==SOCKET_ERROR)
  33. ErrorHandling("bind() error");
  34. if(listen(hServSock, 5)==SOCKET_ERROR)
  35. ErrorHandling("listen() error");
  36. while(1)
  37. {
  38. clntAdrSize=sizeof(clntAdr);
  39. hClntSock=accept(hServSock, (SOCKADDR*)&clntAdr, &clntAdrSize);
  40. printf("Connection Request : %s:%d\n",
  41. inet_ntoa(clntAdr.sin_addr), ntohs(clntAdr.sin_port));
  42. hThread=(HANDLE)_beginthreadex(
  43. NULL, 0, RequestHandler, (void*)hClntSock, 0, (unsigned *)&dwThreadID);
  44. }
  45. closesocket(hServSock);
  46. WSACleanup();
  47. return 0;
  48. }
  49. unsigned WINAPI RequestHandler(void *arg)
  50. {
  51. SOCKET hClntSock=(SOCKET)arg;
  52. char buf[BUF_SIZE];
  53. char method[BUF_SMALL];
  54. char ct[BUF_SMALL];
  55. char fileName[BUF_SMALL];
  56. recv(hClntSock, buf, BUF_SIZE, 0);
  57. if(strstr(buf, "HTTP/")==NULL)
  58. {
  59. SendErrorMSG(hClntSock);
  60. closesocket(hClntSock);
  61. return 1;
  62. }
  63. strcpy(method, strtok(buf, "/"));
  64. if(strcmp(method, "GET "))
  65. SendErrorMSG(hClntSock);
  66. strcpy(fileName, strtok(NULL, " "));
  67. strcpy(ct, ContentType(fileName));
  68. SendData(hClntSock, ct, fileName);
  69. return 0;
  70. }
  71. void SendData(SOCKET sock, char* ct, char* fileName)
  72. {
  73. char protocol[]="HTTP/1.0 200 OK\r\n";
  74. char servName[]="Server:simple web server\r\n";
  75. char cntLen[]="Content-length:2048\r\n";
  76. char cntType[BUF_SMALL];
  77. char buf[BUF_SIZE];
  78. FILE* sendFile;
  79. sprintf(cntType, "Content-type:%s\r\n\r\n", ct);
  80. if((sendFile=fopen(fileName, "r"))==NULL)
  81. {
  82. SendErrorMSG(sock);
  83. return;
  84. }
  85. send(sock, protocol, strlen(protocol), 0);
  86. send(sock, servName, strlen(servName), 0);
  87. send(sock, cntLen, strlen(cntLen), 0);
  88. send(sock, cntType, strlen(cntType), 0);
  89. while(fgets(buf, BUF_SIZE, sendFile)!=NULL)
  90. send(sock, buf, strlen(buf), 0);
  91. closesocket(sock);
  92. }
  93. void SendErrorMSG(SOCKET sock)
  94. {
  95. char protocol[]="HTTP/1.0 400 Bad Request\r\n";
  96. char servName[]="Server:simple web server\r\n";
  97. char cntLen[]="Content-length:2048\r\n";
  98. char cntType[]="Content-type:text/html\r\n\r\n";
  99. char content[]="<html><head><title>NETWORK</title></head>"
  100. "<body><font size=+5><br>发生错误!"
  101. "</font></body></html>";
  102. send(sock, protocol, strlen(protocol), 0);
  103. send(sock, servName, strlen(servName), 0);
  104. send(sock, cntLen, strlen(cntLen), 0);
  105. send(sock, cntType, strlen(cntType), 0);
  106. send(sock, content, strlen(content), 0);
  107. closesocket(sock);
  108. }
  109. char* ContentType(char* file)
  110. {
  111. char extension[BUF_SMALL];
  112. char fileName[BUF_SMALL];
  113. strcpy(fileName, file);
  114. strtok(fileName, ".");
  115. strcpy(extension, strtok(NULL, "."));
  116. if(!strcmp(extension, "html")||!strcmp(extension, "htm"))
  117. return "text/html";
  118. else
  119. return "text/plain";
  120. }
  121. void ErrorHandling(char* message)
  122. {
  123. fputs(message, stderr);
  124. fputc('\n', stderr);
  125. exit(1);
  126. }

4.实验结果:
No
Yes

5.实验总结
感觉这次学到了很多东西,主要是知道了HTTP协议,并懂得了如何初步处理它.在实验过程中也遇到了各种各样的问题,比如消息行的处理等.这次没有写图形界面了,感觉好难写不出来.还有就是由于HTTP是无状态的协议,所以最好是来个while循环发送消息,不然很容易看不到内容.

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注