http代理服务器C语言

  • D6_244054
    了解作者
  • 2.7MB
    文件大小
  • rar
    文件格式
  • 0
    收藏次数
  • VIP专享
    资源类型
  • 0
    下载次数
  • 2022-05-21 01:49
    上传日期
以前上TCP/IP课程时做的课程设计,很小的一个HTTP代理服务器,基于socket编程。VC6.0环境的。原创程序。 那时候还是新手,程序很简陋,不过好歹能用。 学校学习相关课程的学生可以参考下,当个课程作业没问题,老手就别下了
代理服务器.rar
  • HttpProxy
  • Debug
  • vc60.pdb
    84KB
  • HttpProxy.obj
    12.2KB
  • vc60.idb
    225KB
  • HttpProxy.ilk
    1.6MB
  • HttpProxy.pch
    5.5MB
  • HttpProxy.pdb
    2.2MB
  • Method.obj
    35.1KB
  • HttpProxy.exe
    1.3MB
  • HttpProxy.ncb
    33KB
  • HttpProxy.dsp
    4.1KB
  • HttpProxy.plg
    881B
  • HttpProxy.dsw
    524B
  • Method.asp
    249B
  • stdafx.h
    1KB
  • HttpProxy.cpp
    296B
  • HttpProxy.opt
    53.5KB
  • Method.cpp
    12.1KB
内容介绍
#pragma comment(lib,"wsock32.lib") #pragma comment(lib,"ws2_32.lib") #include <process.h> #include <winsock2.h> #include <afx.h rel='nofollow' onclick='return false;'> #include <afxwin.h rel='nofollow' onclick='return false;'> #include "stdafx.h" #define FD_NOEVENT 0 #define BACKUP 100 #define MAXDATALEN 65535 int ListenPort; SOCKET ListenSock; bool WsaStartupInfo; typedef struct _CLIENTINFO { SOCKET clientsock; sockaddr_in clientsockaddr; } CLIENTINFO, *PCLIENTINFO; CLIENTINFO HttpClientInfo; // typedef struct _SOCKINFO { SOCKET client_sock; SOCKET server_sock; } SOCKINFO, *PSOCKINFO; SOCKINFO HttpSockInfo; extern long SocketEventId(SOCKET remotesock); extern unsigned long GetLocalIp(); extern unsigned long GetDomainIp(char domainname[250]); extern void WsaStart(); extern int StartServer(int listenport); extern UINT StartHttpProxy(int info); extern UINT ServerThread(LPVOID info); extern UINT SendThread(LPVOID info); extern UINT ReciveThread(LPVOID info); extern UINT SendThread(LPVOID info); void exit(); void WsaStart() { WSADATA WsaData; WORD wsaVer; //WORD A 16-bit unsigned integer. wsaVer = MAKEWORD(2, 0); //The MAKEWORD macro creates an unsigned 16-bit integer by concatenating two given unsigned character values. WsaStartupInfo = false; if (WSAStartup(wsaVer, &WsaData) == 0) { WsaStartupInfo = true; // printf("WSAStartup\n"); } } int StartServer(int listenport)//开始代理服务 { //printf("监听端口%d",ListenPort); StartHttpProxy(listenport); // _beginthread((void (*) (void *)) StartHttpProxy, 0, (LPVOID)NULL); // AfxBeginThread(StartHttpProxy, (LPVOID)NULL); //创建线程,执行StartHttpProxy函数。 return 1; } UINT StartHttpProxy(int info) //一个线程,监听代理服务的端口 { printf("代理服务器启动....\n"); //端口监听线程 ListenPort=info; SOCKET NewSock; //定义一个套接字 int socklen; //定义一个整形变量用来存放长度 sockaddr_in serversock, remotesock_addr; //定义两个地址 serversock.sin_family = AF_INET; //sin_family指代协议族,在socket编程中只能是AF_INET serversock.sin_addr.S_un.S_addr = INADDR_ANY;//INADDR_ANY表示任何可绑定的地址 serversock.sin_port = htons(ListenPort);//将HttpListenPort中的端口号赋值给sin_port // Sleep(300); ListenSock = socket(AF_INET, SOCK_STREAM, 0);//全局变量HttpListenSock // printf("创建套接字...\n"); if (ListenSock == INVALID_SOCKET) //INVALID_SOCKET { printf("创建套接字失败,返回值值是:%d\n",ListenSock); return 0; } // Sleep(300); // printf("创建套接字成功\n"); if (bind(ListenSock, (const sockaddr*) &serversock, sizeof(serversock))== SOCKET_ERROR)//绑定套接字 { printf("bind error."); return 0; } // printf("bind.\n"); // Sleep(300); listen(ListenSock, BACKUP);//监听套接字HttpListenSock // printf("listen.\n"); socklen = sizeof(remotesock_addr); // Sleep(100); while (true) { printf("等待客户机连接....\n"); NewSock = accept(ListenSock, (sockaddr*) &remotesock_addr, &socklen);//被动套接字 if (NewSock == INVALID_SOCKET)//判断被动套接字是否有效 { Sleep(10); continue; } // printf("被动套接字创建成功\n"); ZeroMemory((void*) &HttpClientInfo, sizeof(CLIENTINFO));//HttpClientInfo是一个全局结构体变量,类型是CLIENTINFO HttpClientInfo.clientsock = NewSock; HttpClientInfo.clientsockaddr = remotesock_addr; AfxBeginThread(ServerThread, (LPVOID) &HttpClientInfo);//创建一个线程运行HttpProxyServerThread函数,HttpClientInfo是形参。 Sleep(100);//延时 } return 1; } UINT ServerThread(LPVOID info) { // printf("开始代理服务\n"); //针对一次服务的线程 PCLIENTINFO pclientinfo;//定义一个结构体变量指针,指向CLIENTINFO类型。 SOCKET connectsock, clientsock;//定义两个套接字 sockaddr_in remotesock_addr; char data[MAXDATALEN], url[250], temp[250], httpurl[250], portnum[10]; int datalen,index_start, index_end, port; CString HttpString, UrlString, PortString;//CString 是VC定义的一个类。这里新建三个CString类的对象。 pclientinfo = (PCLIENTINFO)info;//将形参的地址赋给指针pclientinfo clientsock = pclientinfo->clientsock; ZeroMemory((void*)data, sizeof(data));//将data初始化为全是0 printf("连接到客户机,接受来自客户机的报文....\n"); datalen = recv(clientsock, data, sizeof(data), 0);//接受来自client的信息,保存在data中 if (datalen <= 0) { printf("接受失败\n"); closesocket(clientsock); return 0; } //以下一段处理HTTP报文url段的代码 //将data中的字符串记录在HttpString对象中 //然后在HttpString中记录的字符串中找url标记的头和尾,位置分别用index_start和index_end标记 //然后将HttpString中的url读取到UrlString对象中。 printf("处理报文信息...\n"); // printf("提取url\n"); HttpString.Format("%s", data); UrlString = HttpString; index_start = HttpString.Find("Host: ", 0); //寻找url标记 if (index_start <= 0) { closesocket(clientsock); return 0; } index_end = HttpString.Find("\r\n", index_start); if (index_end <= 0) { closesocket(clientsock); return 0; } UrlString = HttpString.Mid(index_start + 6, index_end - index_start - 6); //读取 url字符串 wsprintf(url, "%s", UrlString); strcpy(temp, url); strcat(temp, ":"); datalen = strlen(temp); if (HttpString.Find("GET", 0) == 0)//如果在报文里找到了GET。则这是一个GET请求的报文 { // printf("这是一个GET\n"); //判断get命令,并处理 index_start = HttpString.Find(temp, 0);//在报文里面从头找url,位置标记到index_start strcpy(httpurl, "http://");//先将http://拷贝到字串httpurl中 if (index_start > 0)//如果找到起始位 { index_end = HttpString.Find("/", index_start);//在报文里从index_start的位置开始找“/”,位置标记在index_end if (index_end <= 0) { closesocket(clientsock); return 0; } PortString = HttpString.Mid(index_start + datalen, index_end - index_start - datalen);//把HttpString中找到的端口号放到PortString里 port = atoi(PortString);//将端口号经过类型转换赋值到port strcat(httpurl, temp);//将temp,也就是url+":"拷贝到httpurl中http://字段的后面。 itoa(port, portnum, sizeof(portnum)); strcat(httpurl, portnum);//将端口号拷贝到httpurl的http://+url+":"后面 strcat(httpurl, "/");//在httpurl的http://+url+":"+端口号后面加上/ } else//否则,没有找到,说明使用了默认的80端口 { port = 80; strcat(httpurl, url); strcat(httpurl, "/"); } HttpString.Replace(httpurl, "/");//将报文中的httpurl替换成/ HttpString.Replace("Proxy-", "");//将Proxy-去掉 HttpString.Replace("HTTP/1.0", "HTTP/1.1");//将报文支持的HTTP版本号换成1.1 } else if (HttpString.Find("CONNECT", 0) == 0) { //判断connect命令并处理 // printf("这是一个CONNECT\n"); index_start = HttpString.Find(temp, 0);//从头开始在报文里找url:,位置标记在index_start if (index_start > 0) { index_end = HttpString.Find(" ", index_start);//从index_start后开始找第一个空格,位置标记在index_end if (index_end <= 0) { closesocket(clientsock); return 0; } PortString = HttpString.Mid(index_start + datalen, index_end - index_start - datalen);//拷贝端口号 port = atoi(PortString);//端口号类型转换 } else { closesocket(clientsock); return 0; } } //将上面提出的信息用开设定与远程主机的连接 // printf("设置远程主机地址与端口\n"); remotesock_addr.sin_family = AF_INET; remotesock_addr.sin_port = htons(port); remotesock_addr.sin_addr.S_un.S_addr = GetDomainIp(url); connectsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); printf("正在连接服务器....\n"); if (connect(connectsock, (const sockaddr*) &remotesock_addr, sizeof(remotesock_addr)) == INVALID_SOCKET) { //连接远程主机 printf("连接服务器失败\n"); closesocket(clientsock); return 0; } ZeroMemory((void*)data, sizeof(data));//清空data wsprintf(data, "%s", HttpString);//将HttpString以字符串输出到data中 datalen = strlen(data);//量一下data的大小 printf("连接服务器成功,向服务器发送HTTP报文\n"); if (HttpString.Find("CONNECT", 0) < 0)//如果HTTP不是CONNECT while (!send(connectsock, data, datalen, 0))//将data,即HttpString的内容发给
评论
    相关推荐