windows下的C++ socket服务器(4)
void handleAccept(int socket_fd)
{
char buf[] = { '\0' };
string cmd;
string filename;
recv(socket_fd, buf, sizeof(buf), );//
stringstream sstream;//
sstream << buf;
sstream >> cmd;
sstream >> filename;
cout << cmd << " " << filename << endl;
if (cmd=="GET")//3
{
ifstream file;
filename = filename.substr(, filename.length() - );
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()), );
while (!file.eof())//6
{
char buf[];
memset(buf, , sizeof(buf));
file.read(buf,sizeof(buf)-);
int n = file.gcount();
send(socket_fd, buf,n,);//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++网络爬虫。
windows下的C++ socket服务器(4)的更多相关文章
- windows下的C++ socket服务器(1)
windows下的一个C++ socket服务器,用到了C++11的相关内容,现在还不是很完善,以后会不断改进的! #include <winsock2.h>//1 以后会用这种方式对特定 ...
- windows下的C++ socket服务器(2)
int main(int ac, char *av[]) { ); ) { exit(); } thread t; ) { int socket_fd = accept(tcp_socket, nul ...
- windows下的C++ socket服务器(3)
int make_server_socket(int port) { WSADATA inet_WsaData; WSAStartup(MAKEWORD(), &inet_WsaData); ...
- windows下运行的linux服务器批量管理工具(带UI界面)
产生背景: 由于做服务器运维方面的工作,需要一人对近千台LINUX服务器进行统一集中的管理,如同时批量对LINUX服务器执行相关的指令.同时批量对LINUX服务器upload程序包.同时批量对LINU ...
- syslog之三:建立Windows下面的syslog日志服务器
目录: <syslog之一:Linux syslog日志系统详解> <syslog之二:syslog协议及rsyslog服务全解析> <syslog之三:建立Window ...
- Windows下搭建本地SVN服务器【转】
转自:http://www.linuxidc.com/Linux/2015-01/111563.htm 本文介绍Windows下搭建本地SVN服务器的方法,网上资料比较少也比较旧,大都介绍的是旧版本S ...
- Windows下IIS搭建Ftp服务器
第一步:启用Windows IIS Web服务器 1.1 控制面板中找到"程序"并打开 1.2 程序界面找到"启用或关闭Windows功能"并打开 1.3 上面 ...
- Windows下svn客户端和服务器的安装使用
svn,全称subversion, 是目前用的较多的开源的版本管理工具.相信有些经历的程序员应该都听说过它. 通常的svn服务器是搭建在Linux中,不过如果作为个人或者单个小组使用的话,就可以把sv ...
- Windows下搭建HTTP/HTTPS服务器及测试过程
1 安装Apache http://www.apachehaus.com/cgi-bin/download.plx 选择合适的版本下载 本次下载的是 Apache 2.4.x VC14 Apache版 ...
随机推荐
- 字符串Hash/树Hash学习笔记
哈希 Tags:字符串 作业部落 评论地址 一.概述 百度百科: 散列表(Hash table/哈希表),是根据关键码值(Key value)而直接进行访问的数据结构. 哈希表常用于比较两个字符串是否 ...
- Python 装饰器笔记
一.装饰器无参数 1.原函数无参数 def wrap_in_tag_b(fn): # wrap_in_tag_b 是真正的装饰器 def wrapped(): return "<b&g ...
- 11-[CSS]-标准文档流,display,浮动,清除浮动,overflow
1.标准文档流 <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...
- CSS快速入门-定位布局(九宫格)
实现效果图: 看上去是不是很屌的样子?其实实现起来主要就是用到了一个float,不难. 实现步骤:1.新建一个大div,300*30002.里面放5个小div,100*1003.将div定位
- PersistentAliasAttribute & CalculatedAttribute & CalculatedPersistentAliasAttribute
一,PersistentAliasAttribute-[XPO提供] Indicates that a property is not persistent and its value is calc ...
- JAVA使用qrcode生成二维码(带logo/不带logo)
/** * */ package qrcode; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Image; i ...
- 通俗理解BFS和DFS,附基本模板
1.BFS(宽度优先搜索):使用队列来保存未被检测的节点,按照宽度优先的顺序被访问和进出队列 打个比方:(1)类似于树的按层次遍历 (2)你的眼镜掉在了地上,你趴在地上,你总是先摸离你最近的地方,如果 ...
- 第1章 Linux命令行简介
1.1 Linux命令行概述 1.2 在Linux命令行下查看命令帮助 1.3 Linux关机.重启.注销命令 1.4 老男孩的运维思想 1.1 Linux命令行概述 1.1.1 Linux命令行的作 ...
- junit测试类防止事务回滚-工作心得
本随笔文章,由个人博客(鸟不拉屎)转移至博客园 发布时间: 2018 年 12 月 06 日 原地址:https://niaobulashi.com/archives/junit-test-rollb ...
- .Net 如何访问主流的各大数据库
做过开发的都知道,.NET基本可以理解是和MSSQL,windows服务器属于一个好的搭档,正如PHP和MYSQL,LIUNX等也可以理解是一个完美搭配:但是在实际的开发中并不完全是这样的,如果你是学 ...