《计算机网络》实验指导书
wVersionRequested = MAKEWORD(2, 2); //加载dll文件Scoket库 err = WSAStartup(wVersionRequested, &wsaData); if(err != 0){ //找不到winsock.dll printf(\加载winsock失败,错误代码为: %d\\n\ return FALSE; } if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) !=2) { printf(\不能找到正确的winsock版本\\n\ WSACleanup(); return FALSE; } ProxyServer= socket(AF_INET, SOCK_STREAM, 0); if(INVALID_SOCKET == ProxyServer){ printf(\创建套接字失败,错误代码为:%d\\n\ return FALSE; } ProxyServerAddr.sin_family = AF_INET; ProxyServerAddr.sin_port = htons(ProxyPort); ProxyServerAddr.sin_addr.S_un.S_addr = INADDR_ANY; if(bind(ProxyServer,(SOCKADDR*)&ProxyServerAddr,sizeof(SOCKADDR)) == SOCKET_ERROR){ printf(\绑定套接字失败\\n\ return FALSE; } if(listen(ProxyServer, SOMAXCONN) == SOCKET_ERROR){ printf(\监听端口%d失败\ return FALSE; } return TRUE; } //************************************ // Method: ProxyThread // FullName: ProxyThread // Access: public // Returns: unsigned int __stdcall // Qualifier: 线程执行函数 // Parameter: LPVOID lpParameter //************************************ unsigned int __stdcall ProxyThread(LPVOID lpParameter){ char Buffer[MAXSIZE];
9
《计算机网络》实验指导书
char *CacheBuffer; ZeroMemory(Buffer,MAXSIZE); SOCKADDR_IN clientAddr; int length = sizeof(SOCKADDR_IN); int recvSize; int ret; recvSize = recv(((ProxyParam *)lpParameter)->clientSocket,Buffer,MAXSIZE,0); if(recvSize <= 0){ goto error; } HttpHeader* httpHeader = new HttpHeader(); CacheBuffer = new char[recvSize + 1]; ZeroMemory(CacheBuffer,recvSize + 1); memcpy(CacheBuffer,Buffer,recvSize); ParseHttpHead(CacheBuffer,httpHeader); delete CacheBuffer; if(!ConnectToServer(&((ProxyParam *)lpParameter)->serverSocket,httpHeader->host)) { goto error; } printf(\代理连接主机 %s 成功\\n\ //将客户端发送的HTTP数据报文直接转发给目标服务器 ret = send(((ProxyParam *)lpParameter)->serverSocket,Buffer,strlen(Buffer) + 1,0); //等待目标服务器返回数据 recvSize = recv(((ProxyParam *)lpParameter)->serverSocket,Buffer,MAXSIZE,0); if(recvSize <= 0){ goto error; } //将目标服务器返回的数据直接转发给客户端 ret = send(((ProxyParam *)lpParameter)->clientSocket,Buffer,sizeof(Buffer),0); //错误处理 error: printf(\关闭套接字\\n\ Sleep(200); closesocket(((ProxyParam*)lpParameter)->clientSocket); closesocket(((ProxyParam*)lpParameter)->serverSocket); delete lpParameter; _endthreadex(0); return 0; }
10
《计算机网络》实验指导书
//************************************ // Method: ParseHttpHead // FullName: ParseHttpHead // Access: public // Returns: void // Qualifier: 解析TCP报文中的HTTP头部 // Parameter: char * buffer // Parameter: HttpHeader * httpHeader //************************************ void ParseHttpHead(char *buffer,HttpHeader * httpHeader){ char *p; char *ptr; const char * delim = \ p = strtok_s(buffer,delim,&ptr);//提取第一行 printf(\ if(p[0] == 'G'){//GET方式 memcpy(httpHeader->method,\ memcpy(httpHeader->url,&p[4],strlen(p) -13); }else if(p[0] == 'P'){//POST方式 memcpy(httpHeader->method,\ memcpy(httpHeader->url,&p[5],strlen(p) - 14); } printf(\ p = strtok_s(NULL,delim,&ptr); while(p){ switch(p[0]){ case 'H'://Host memcpy(httpHeader->host,&p[6],strlen(p) - 6); break; case 'C'://Cookie if(strlen(p) > 8){ char header[8]; ZeroMemory(header,sizeof(header)); memcpy(header,p,6); if(!strcmp(header,\ memcpy(httpHeader->cookie,&p[8],strlen(p) -8); } } break; default: break; } p = strtok_s(NULL,delim,&ptr);
11
《计算机网络》实验指导书
} } //************************************ // Method: ConnectToServer // FullName: ConnectToServer // Access: public // Returns: BOOL // Qualifier: 根据主机创建目标服务器套接字,并连接 // Parameter: SOCKET * serverSocket // Parameter: char * host //************************************ BOOL ConnectToServer(SOCKET *serverSocket,char *host){ sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(HTTP_PORT); HOSTENT *hostent = gethostbyname(host); if(!hostent){ return FALSE; } in_addr Inaddr=*( (in_addr*) *hostent->h_addr_list); serverAddr.sin_addr.s_addr = inet_addr(inet_ntoa(Inaddr)); *serverSocket = socket(AF_INET,SOCK_STREAM,0); if(*serverSocket == INVALID_SOCKET){ return FALSE; } if(connect(*serverSocket,(SOCKADDR *)&serverAddr,sizeof(serverAddr)) == SOCKET_ERROR){ closesocket(*serverSocket); return FALSE; } return TRUE; } 7.实验报告
在实验报告中需要总结说明:
(1)Socket编程的客户端和服务器端主要步骤; (2)HTTP代理服务器的基本原理; (3)HTTP代理服务器的程序流程图;
(4)实现HTTP代理服务器的关键技术及解决方案; (5)HTTP代理服务器实验验证过程以及实验结果; (6)HTTP代理服务器源代码(带有详细注释)。
12