下面这个例子我怎么做也做不出来,请高手介绍下应该怎样做,谢谢用 VC++ 和 Winsock 实现与 HTTP 服务器通话 
作者:Ji Hong 
 
一、引 言 
---- Windows Socket API是一套开放的、支持多种协议的Windows下的网络编程接口,它包 括一个标准的 Berkeley Socket功能调用的集合,以及为Windows所作的重要扩充。 Windows Socket经过不断完善并在众 多公司的全力支持下,已成为Windows网络编程 的事实上的标准。 ---- 本 文 将 在VC++ 5.0 环 境 下 介 绍 一个基于 Winsock 的 HTTP 客户应用程序。 读者可以基于本例 同样的原理实现其他Internet常用协议(time, SMTP, POP3, Telnet, FTP 等)的客户应用程序。 二、一个简单的浏览器 
---- 我将创建一个简单的浏览器,以说明如何通过Winsock基于HTTP协议实现HTTP 客户应 用程序。 ---- 首先我将创建一个帮助函数 LogFile(),该函数把传递给它的字符串写到磁盘文件 中。然后再创建 本示例的核心函数 -- HttpClient() 。在这个核心函数中,我将通 过 Winsock 连接到 HTTP 服务器上 (本例中我将使用计算机世界日报 168.160.224.185)。当连接成功后,发送 Get 命令到 HTTP 服务器 去下载指定路径 上(/99/tips/)的文件。通过帮助函数 LogFile() 把下载的数据记录到本地磁盘文 件中。 char fname[MAXPATH]; 
void LogFile(char *p) 

FILE *fp=fopen(fname,"a+"); 
fprintf(fp,"%s ",p); 
fclose(fp); 
} BOOL HttpClient(void) 

WSADATA ws; 
SOCKET s; 
struct sockaddr_in addr; int iResult; 
long lResult; 
char strSubAddr[100], strBuffer[100]; lResult = WSAStartup(0x0101,&ws); 
s = socket(AF_INET,SOCK_STREAM,0); addr.sin_family = AF_INET; 
addr.sin_port = htons(80); 
addr.sin_addr.s_addr = inet_addr 
("168.160.224.185"); // 计算机世界日报 
iResult=connect(s,(struct sockaddr *) 
&addr, sizeof(addr)); 
if(SOCKET_ERROR == iResult) 

// 连接失败 
WSACleanup(); 
return FALSE; 

else { 
// 连接成功 
strcpy(strSubAddr, "GET /99/tips/ "); 
strcpy(fname, "index.htm"); 
iResult = send(s, strSubAddr,strlen(strSubAddr),0); // 下载文件 
do { 
strset(strBuffer,' '); 
iResult = recv(s,strBuffer,sizeof(strBuffer),0); 
LogFile(strBuffer); 
} while( iResult !=0 ); 
} WSACleanup(); 
return TRUE; 
} 三、测试 
---- 打开Visual C++ 5.0, 用MFC创建基于对话框的工程Test, 并在对话框上放 置"Test" 按 钮, 然后添加测试代码。 Void CTestDlg::OnTest() 

HttpClient(); 
} ---- 编译并运行该测试程序,在测试对话框中,单击 "Test" 按钮, ---- "http://www.computerworld.com.cn/99/tips/"的index.htm文件将被下载到本地。 四. 结 论 
---- 这应该就是Netscape Navigator,Internet Explorer以及其他浏览器实现Internet访 问的基本代码了. 在这些浏览器中,其他百分之九十以上的代码主要用于HTML显示等 本地处理上。 ---- 读者如果有兴趣,基于这些代码,再加入一些解释HTML命令的代码,就可以正确显示 所下载的HTML文件, 那也就是说将拥有自己版本的一个百分之百的浏览器了。何不一试 ?
 
 

解决方案 »

  1.   

    我是新手.
    谁可以把这个例子的每一个步骤写出来,可把做好的工程发给我好吗?
    [email protected]
    谢谢
      

  2.   

    你错在哪里呢?
    是不是有头文件没有包含进。。socket是需要库的。
      

  3.   

    void CGetWebDlg::OnBnClickedOk()
    {

     HttpClient();
     MessageBox("执行完成");
    }
    char fname[MAXPATH]; 
    void LogFile(char *p) 

    //FILE *fp=fopen(fname,"a+"); 
    //fprintf(fp,"%s ",p); 
    //fclose(fp); 
    CStdioFile file;
    file.Open(fname,CFile::modeCreate|CFile::modeWrite);
    file.Write(p,sizeof(p));
    file.Close();

    } BOOL HttpClient(void) 

    WSADATA ws; 
    SOCKET s; 
    struct sockaddr_in addr; int iResult; 
    long lResult; 
    char strSubAddr[2000], strBuffer[1024]; lResult = WSAStartup(0x0101,&ws); 
    s = socket(AF_INET,SOCK_STREAM,0); addr.sin_family = AF_INET; 
    addr.sin_port = htons(80); 
    addr.sin_addr.s_addr = inet_addr 
    ("202.108.23.82"); // www.hao123.com
    iResult=connect(s,(struct sockaddr *) 
    &addr, sizeof(addr)); 
    if(SOCKET_ERROR == iResult) 

    // 连接失败 
    WSACleanup(); 
    return FALSE; 

    else { 
    // 连接成功 
    char request[1024]="GET /index.htm HTTP/1.1\r\n";
    strcat(request,"Accept: */");
    strcat(request,"*\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)\r\n");
    strcat(request,"Host: 202.108.23.82\r\n");
    strcat(request,"Connection: Keep-Alive\r\n\r\n");strcpy(fname, "index.htm"); 
    iResult = send(s, request,strlen(request),0); // 下载文件 
    do { 
    strset(strBuffer,' '); 
    iResult = recv(s,strBuffer,sizeof(strBuffer),0); 
    LogFile(strBuffer); 
    } while( iResult !=0 ); 
    } WSACleanup(); 
    return TRUE; 
    }
      

  4.   

    注意,http请求是有格式的,你可以到网上找一下相关资料,
      

  5.   

    谢谢tooker(小菜)
    但不是是不是我机的问题,程序很容易死.
    发现是循环中recv的问题
    do { 
    strset(strBuffer,' '); 
    iResult = recv(s,strBuffer,sizeof(strBuffer),0); 
    //////LogFile(strBuffer); 已注释掉,说明不关LogFile的是
    } while( iResult !=0 ); 
    就是读到最后一部分时出问题.
    还有,如果要做如下例子,应该怎样做呢?
                                用Socket类实现HTTP协议客户端应用
                       来源:中国协议分析网  作者:  编辑:电脑农民  浏览:4460人次              
                  
                 Http客户端程序已集成在Java语言中,可以通过URLConnection类调用。遗憾的
                是,由于SUN没有公布Http客户程序的源码,它实现的细节仍是一个谜。本文根据HTTP
                协议规范,用Java.net.Socket类实现一个HTTP协议客户端程序。            1.Socket类:
                了解TCP/IP协议集通信的读者知道,协议间的通信是通过Socket完成的。在
                Java.net包中,Socket类就是对Socket的具体实现。它通过连接到主机后,返回一个
                I/O流,实现协议间的信息交换。            2.HTTP协议
                HTTP协议同其它TCP/IP协议集中的协议一样,是遵循客户/服务器模型工作的。客
                户端发往服务端的信息格式如下:
                ------------------------------
                请求方法URLHTTP协议的版本号
                提交的元信息
                **空行**
                实体
                ------------------------------
                请求方法是对这次连接工作的说明,目前HTTP协议已经发展到1.1版,它包括GET、
                HEAD、POST、DELETE、OPTIONS、TRACE、PUT七种。元信息是关于当前请求的信息。通
                过分析元信息,可以检查实体数据是否完整,接收过程是否出错,类型是否匹配等。元
                信息的引入使HTTP协议通信更加稳妥可靠。实体是请求的具体内容。
                将上述报文发往Web服务器,如果成功,应答格式如下:
                --------------------------------
                HTTP协议的版本号应答状态码应答状态码说明
                接收的元信息
                **空行**
                实体
                --------------------------------
                以上报文发向客户端,并且接收成功,彼此间关闭连接,完成一次握手。
                下面用最常用的GET方法,来说明具体的报文应用
                ----------------------------------
                GEThttp://www.youhost.comHTTP/1.0
                accept:www/source;text/html;image/gif;image/jpeg;*/*
                User_Agent:myAgent
                **空行**
                -----------------------------------
                这个报文是向www.youhost.com主机请求一个缺省HTML文档。客户端HTTP协议版本
                号是1.0版,元信息包括可接收的文件格式,用户代理,每一段之间用回车换行符分
                隔,最后以一个空行结束。发向服务器后,如果执行过程正常,服务器返回以下代码:
                ------------------------------------
                HTTP/1.1200OK
                Date:Tue,14Sep199902:19:57GMT
                Server:Apache/1.2.6
                Connection:close
                Content-Type:text/html
                **空行**
                ......
                ------------------------------------
                HTTP/1.1表示这个HTTP服务器是1.1版,200是服务器对客户请求的应答状态码,OK
                是对应答状态码的解释,之后是这个文档的元信息和文档正文。(相关应答状态码和元
                信息的解释请参阅Inetrnet标准草案:RFC2616)。            3.HTTP客户端程序:            importjava.net.*;
                importjava.io.*;
                importjava.util.Properties;
                importjava.util.Enumeration;
                publicclassHttp{
                protectedSocketclient;
                protectedBufferedOutputStreamsender;
                protectedBufferedInputStreamreceiver;
                protectedByteArrayInputStreambyteStream;
                protectedURLtarget;
                privateintresponseCode=-1;
                privateStringresponseMessage="";
                privateStringserverVersion="";
                privatePropertiesheader=newProperties();
                publicHttp(){}
                publicHttp(Stringurl){
                GET(url);
                }
                /*GET方法根据URL,会请求文件、数据库查询结果、程序运行结果等多种内容*/
                publicvoidGET(Stringurl){
                try{
                checkHTTP(url);
                openServer(target.getHost(),target.getPort());
                Stringcmd="GET"+getURLFormat(target)+"HTTP/1.0\r\n"
                +getBaseHeads()+"\r\n";
                sendMessage(cmd);
                receiveMessage();
                }catch(ProtocolExceptionp){
                p.printStackTrace();
                return;
                }catch(UnknownHostExceptione){
                e.printStackTrace();
                return;
                }catch(IOExceptioni)            i.printStackTrace();
                return;
                }
                }            /*
                *HEAD方法只请求URL的元信息,不包括URL本身。若怀疑本机和服务器上的
                *文件相同,用这个方法检查最快捷有效。
                */
                publicvoidHEAD(Stringurl){
                try{
                checkHTTP(url);
                openServer(target.getHost(),target.getPort());
                Stringcmd="HEAD"+getURLFormat(target)+"HTTP/1.0\r\n"
                +getBaseHeads()+"\r\n";
                sendMessage(cmd);
                receiveMessage();
                }catch(ProtocolExceptionp){
                p.printStackTrace();
                return;
                }catch(UnknownHostExceptione){
                e.printStackTrace();
                return;
                }catch(IOExceptioni)            i.printStackTrace();
                return;
                }
                }
      

  6.   

    /*
                *POST方法是向服务器传送数据,以便服务器做出相应的处理。例如网页上常用的
                *提交表格。
                */
                publicvoidPOST(Stringurl,Stringcontent){
                try{
                checkHTTP(url);
                openServer(target.getHost(),target.getPort());
                Stringcmd="POST"+getURLFormat(target)+"
                HTTP/1.0\r\n"+getBaseHeads();
                cmd+="Content-type:application/x-www-form-urlencoded\r\n";
                cmd+="Content-length:"+content.length()+"\r\n\r\n";
                cmd+=content+"\r\n";
                sendMessage(cmd);
                receiveMessage();
                }catch(ProtocolExceptionp){
                p.printStackTrace();
                return;
                }catch(UnknownHostExceptione){
                e.printStackTrace();
                return;
                }catch(IOExceptioni)            i.printStackTrace();
                return;
                }            }
                protectedvoidcheckHTTP(Stringurl)throwsProtocolException{
                try{
                URLtarget=newURL(url);
                if(target==null||!target.getProtocol().toUpperCase().equals("HTTP"))
                thrownewProtocolException("这不是HTTP协议");
                this.target=target;
                }catch(MalformedURLExceptionm){
                thrownewProtocolException("协议格式错误");
                }
                }
                /*
                *与Web服务器连接。若找不到Web服务器,InetAddress会引发UnknownHostException
                *异常。若Socket连接失败,会引发IOException异常。
                */
                protectedvoidopenServer(Stringhost,intport)throws
                UnknownHostException,IOException{
                header.clear();
                responseMessage="";responseCode=-1;
                try{
                if(client!=null)closeServer();
                if(byteStream!=null){
                byteStream.close();byteStream=null;
                }
                InetAddressaddress=InetAddress.getByName(host);
                client=newSocket(address,port==-1?80:port);
                sender=newBufferedOutputStream(client.getOutputStream());
                receiver=newBufferedInputStream(client.getInputStream());
                }catch(UnknownHostExceptionu){
                throwu;
                }catch(IOExceptioni){
                throwi;
                }
                }
                /*关闭与Web服务器的连接*/
                protectedvoidcloseServer()throwsIOException{
                if(client==null)return;
                try{
                client.close();sender.close();receiver.close();
                }catch(IOExceptioni){
                throwi;
                }
                client=null;sender=null;receiver=null;
                }
                protectedStringgetURLFormat(URLtarget){
                Stringspec="http://"+target.getHost();
                if(target.getPort()!=-1)
                spec+=":"+target.getPort();
                returnspec+=target.getFile();
                }            /*向Web服务器传送数据*/
                protectedvoidsendMessage(Stringdata)throwsIOException{
                sender.write(data.getBytes(),0,data.length());
                sender.flush();
                }
                /*接收来自Web服务器的数据*/
                protectedvoidreceiveMessage()throwsIOException{
                bytedata[]=newbyte[1024];
                intcount=0;
                intword=-1;
                //解析第一行
                while((word=receiver.read())!=-1){
                if(word=='\r'||word=='\n'){
                word=receiver.read();
                if(word=='\n')word=receiver.read();
                break;
                }
                if(count==data.length)data=addCapacity(data);
                data[count++]=(byte)word;
                }
                Stringmessage=newString(data,0,count);
                int=message.indexOf(32);
                serverVersion=message.substring(0,);
                while(responseCode=Integer.parseInt(message.substring(+1,+=4));
                responseMessage=message.substring(,message.length()).trim();            //应答状态码和处理请读者添加
                switch(responseCode){
                case400:
                thrownewIOException("错误请求");
                case404:
                thrownewFileNotFoundException(getURLFormat(target));
                case503:
                thrownewIOException("服务器不可用");
                }
                if(word==-1)thrownewProtocolException("信息接收异常终止");
                intsymbol=-1;
                count=0;
                //解析元信息
                while(word!='\r'&&word!='\n'&&word>-1){
                if(word=='\t')word=32;
                if(count==data.length)data=addCapacity(data);
                data[count++]=(byte)word;
                parseLine:{
                while((symbol=receiver.read())>-1){
                switch(symbol){
                case'\t':
                symbol=32;break;
                case'\r':
                case'\n':
                word=receiver.read();
                if(symbol=='\r'&&word=='\n'){
                word=receiver.read();
                if(word=='\r')word=receiver.read();
                }
                if(word=='\r'||word=='\n'||word>32)breakparseLine;
                symbol=32;break;
                }
                if(count==data.length)data=addCapacity(data);
                data[count++]=(byte)symbol;
                }
                word=-1;
                }
                message=newString(data,0,count);
                =message.indexOf(':');
                Stringkey=null;
                if(>0)key=message.substring(0,);
                ++;
                while(Stringvalue=message.substring(,message.length());
                header.put(key,value);
                count=0;
                }
                //获得正文数据
                while((word=receiver
                if(count>0)byteStream=newByteArrayInputStream(data,0,count);
                data=null;
                closeServer();
                }
                publicStringgetResponseMessage(){
                returnresponseMessage;
                }
                publicintgetResponseCode(){
                returnresponseCode;
                }
                publicStringgetServerVersion(){
                returnserverVersion;
                }
                publicInputStreamgetInputStream(){
                returnbyteStream;
                }
                publicsynchronizedStringgetHeaderKey(inti){
                if(i>=header.size())returnnull;
                Enumerationenum=header.propertyNames();
                Stringkey=null;
                for(intj=0;j<=i;j++)
                key=(String)enum.nextElement();
                returnkey;
                }
                publicsynchronizedStringgetHeaderValue(inti){
                if(i>=header.size())returnnull;
                returnheader.getProperty(getHeaderKey(i));
                }
                publicsynchronizedStringgetHeaderValue(Stringkey){
                returnheader.getProperty(key);
                }
                protectedStringgetBaseHeads(){
                Stringinf="User-Agent:myselfHttp/1.0\r\n"+
                "Accept:www/source;text/html;image/gif;*/*\r\n";
                returninf;
                }
                privatebyte[]addCapacity(byterece[]){
                bytetemp[]=newbyte[rece.length+1024];
                System.arraycopy(rece,0,temp,0,rece.length);
                returntemp;
                }
                }            注:程序中只实现GET、HEAD、POST三种方法。其他几种因不常使用,暂且忽略。