windows下之C++ socket服务器(4)

void handleAccept(int socket_fd)
{
    char buf[1024] = { '\0' };
    string cmd;
    string filename;
    recv(socket_fd, buf, sizeof(buf), 0);//1
    stringstream sstream;//2
    sstream << buf;
    sstream >> cmd;
    sstream >> filename;
    cout << cmd << " " << filename << endl;
    if (cmd=="GET")//3
    {
        ifstream file;
        filename = filename.substr(1, filename.length() - 1);
        file.open(filename ,ifstream::binary);//4
        string head = "HTTP/1.0 200 OK\r\nContent - type:text/plain\r\n\r\n";//5
        if (!file)
        {
            cout << "fail" << endl;
            closesocket(socket_fd);
            return;
        }
        if (filename.find(".html")!=string::npos|| filename.find(".htm")!=string::npos)
        {
            head = "HTTP/1.0 200 OK\r\nContent - type:text/html\r\n\r\n";
        }        
        if (filename.find(".png")!=string::npos)
        {
            head = "HTTP/1.0 200 OK\r\nContent - type:image/png\r\n\r\n";    
        }
        if (filename.find(".jpg")!=string::npos)
        {
            head = "HTTP/1.0 200 OK\r\nContent - type:image/jpg\r\n\r\n";        
        }
        send(socket_fd, head.c_str(), strlen(head.c_str()), 0);
        while (!file.eof())//6
        {    
            char buf[1024];
            memset(buf, 0, sizeof(buf));
            file.read(buf,sizeof(buf)-1);
            int n = file.gcount();
            send(socket_fd, buf,n,0);//1
        }
        file.close();//7
    }
    closesocket(socket_fd);//7

}

1 recv(socket_fd, buf, sizeof(buf), 0)和send(socket_fd, buf,n,0);

recv用于吸纳从客户端发送来之消息,send用于为服务端发送信息

recv/send函数原型如下

int recv(SOCKET s,char FAR * buf,int len,int flags)/int send(SOCKET
s,const char FAR * buf,int len,int flags);

先是个参数表示代表对方的socket,

老二个参数为接受读取的消息的字符串

老三单参数为该字符串的深浅

季单参数可以据此来决定读写操作

该值可以啊转几乎种

0

MSG_DONTROUTE:不找路由表/* send without using routing tables */
MSG_OOB:接受或发送带他数据 /* process out-of-band data */

MSG_PEEK:查看数据,并无打系统缓冲区移走多少/* peek at incoming message
*/
MSG_WAITALL :等待其他数/* do not complete until packet is
completely filled */

etc…

解释:
MSG_DONTROUTE:是send函数使用的标志.这个标志告诉IP协议.目的主机在本地网络上面,没有必要查找路由表.这个标志一般用网络诊断和路由程式里。
MSG_OOB:表示能接和发送带客的数据.关于带客数据我们之后会说的.
MSG_PEEK:是recv函数的用标志,表示只是从网缓冲区中读取内容,而无散系统缓冲区的始末。这样下次读之时刻,仍然是一律的内容。一般以有多个经过读写多少常常能使此标志。

MSG_WAITALL:是recv函数的采用标志,表示相当及另外的信达时才返回。使用这标志的时刻recv会晤直接不通,直到指定的规格满足,或是发生了错误。

    1)当读到了点名的字节时,函数正常返回,返回值等于len

    2)当读到了文档的最后时,函数正常返回.返回值小于len

    3)当操作发生误时,返回-1,且布局错误吗相应的错号(errno)
其它的几个挑选,但是咱实在用底非常少.

 

有关其他的发送和收取函数

recvfrom/sendto

立刻点儿只函数一般用当UDP中。

函数原型如下

int  recvfrom(SOCKET s,char FAR * buf,int len,int flags,struct sockaddr
FAR * from,int FAR * fromlen);

int  sendto(SOCKET s,const char FAR * buf,int len,int flags,const
struct sockaddr FAR * to,int tolen);

 

2 stringstream sstream;

字符串读写流,这里用于将char
buf[1024]的数据据默认的间隔符读到cmd和filename中,关于cmd和filename的现实意思见3

为得用来用数字转换为字符串

例如

stringstream sstream;

sstream <<123456789;
string a;
sstream >> a;
cout << a << endl;

以数字123456789变为字符串

 

 

3 HTTP协议要

当客户端连接到服务端时,会发出一个http请求

http请求由三组成部分组成,分别是:请求行、消息报头、请求正文

这里只对要求行进行介绍

吁求行以一个智符号开头,以空格分开,后面随着请求的URI和协议的版,格式如下:Method
Request-URI HTTP-Version CRLF  

其中
Method表示请方法;Request-URI是一个合资源标识符;HTTP-Version表示求的HTTP协议版本;CRLF表示回车和换行(除了当最后的CRLF外,不允许出现单独的CR或LF字符)。

告方法(所有方均否题写)有多,各个艺术的说如下:
GET     请求获取Request-URI所标识的资源
POST    在Request-URI所标识的资源后附加新的数额
HEAD    请求获取由Request-URI所标识的资源的应消息报头
PUT     请求服务器存储一个资源,并为此Request-URI作为那个标识
DELETE  请求服务器删除Request-URI所标识的资源
TRACE   请求服务器回送收到的乞求信息,主要用来测试或确诊
CONNECT 保留将来使
OPTIONS 请求查询服务器的性,或者查询及资源相关的抉择和需要

以本程序中不过针对GET请求进行处理,将呼吁方法读入cmd中,和Request-URL读入filename中,判断是否为GET,并取得请求的资源名称

 

4 file.open(filename ,ifstream::binary);

开拓客户所求的公文,这里用二进制的章程打开是为好对图片展开传输

 

 

5 string head = “HTTP/1.0 200 OK\r\nContent –
type:text/plain\r\n\r\n”;

于接收和说请求消息继,服务器返回一个HTTP响应消息。

HTTP响应也是由三单有组成,分别是:状态行、消息报头、响应正文

1)、状态行格式如下:
HTTP-Version Status-Code Reason-Phrase CRLF

其中,HTTP-Version表示服务器HTTP协议的版本;Status-Code表示服务器发回之应状态代码;Reason-Phrase表示状态代码的文本描述。

普遍状态代码、状态描述、说明:

200 OK      //客户端请求成功
400 Bad Request  //客户端请求有语法错误,不能够于服务器所知道
401 Unauthorized
//请求未经授权,这个状态代码必须与WWW-Authenticate报头域一起利用 
403 Forbidden  //服务器收到请求,但是拒绝提供服务
404 Not Found  //请求资源不设有,eg:输入了左的URL
500 Internal Server Error //服务器发生不可预期的错误
503 Server Unavailable 
//服务器时莫可知处理客户端的请求,一段时间后或恢复正常

 

Content-Type表示着传输的品类

Content – type:text/plain:普通文书

Content – type:text/html:html网页

Content – type:image/png:png图片

Content – type:image/jpg:jpg图片

2)响应报头允许服务器传递不可知放在状态行中的叠加响应信息,以及有关服务器的信及指向Request-URI所标识的资源开展下一致步访问的信。在当下不举行详细介绍

3)响应正文就是服务器返回的资源的始末

 关于http协议重新详实的一些足参见http://blog.csdn.net/gueter/article/details/1524447 HTTP协和详解

 

 

6 获得响应正文并勾画到客户端

char buf[1024];
memset(buf, 0, sizeof(buf));//初始化

file.read(buf,sizeof(buf)-1);//由于我们采取二进制的点子打开的文件所以采取了read方法

int n =
file.gcount();//gcount()返回最后一个非格式化的抽取方法读取的字符数,因为偶然读到的会晤小于1023只

send(socket_fd, buf,n,0);//将buf中之n个字符发送至客户端

 

7

file.close()和closesocket(socket_fd)

关门打开的公文以及socket_fd

 

 程序代码下载:http://files.cnblogs.com/magicsoar/WebServer.rar

p.s

次第召开的尚未是好圆满,对部分景象仍send,reve是否在推行呢尚未开展反省,客户端请求的文件不在呢从来不回去404,

我会在随后对程序进行完善之,并以有些初的经验写出来。

率先破写博客,希望大家会指出自身之贫乏来,我会虚心接受并改善之。

属下去可能会见拿团结很一异常二举行的软件,游戏以出来,写一描写,与大家大快朵颐,或者是读书之体验等,也可能会见是本身手上在攻读C++网络爬虫。