- 📙 Interested in Backend Dev && Cloud Native
- ⚡ Golang / Python / C++.
- 🐱 CatKeeper
qinguoyi / tinywebserver Goto Github PK
View Code? Open in Web Editor NEW:fire: Linux下C++轻量级WebServer服务器
License: Apache License 2.0
:fire: Linux下C++轻量级WebServer服务器
License: Apache License 2.0
请问,http_conn类中improv和timer_flag两个变量分别代表什么含义,起到什么作用?
bool http_conn::write()
{
int temp = 0;
if (bytes_to_send == 0)
{
modfd(m_epollfd, m_sockfd, EPOLLIN, m_TRIGMode);
init();
return true;
}
//int mv0len = m_iv[0].iov_len;
while (1)
{
temp = writev(m_sockfd, m_iv, m_iv_count);
if (temp < 0)
{
if (errno == EAGAIN)
{
modfd(m_epollfd, m_sockfd, EPOLLOUT, m_TRIGMode);
return true;
}
unmap();
return false;
}
bytes_have_send += temp;
bytes_to_send -= temp;
if (bytes_have_send >= m_iv[0].iov_len)
{
m_iv[0].iov_len = 0;
m_iv[1].iov_base = m_file_address + (bytes_have_send - m_write_idx);
m_iv[1].iov_len = bytes_to_send;
//printf("1: >= \n");
}
else
{
m_iv[0].iov_base = m_write_buf + bytes_have_send;
m_iv[0].iov_len = m_iv[0].iov_len - bytes_have_send;
//printf("2: < \n");
}
// if (bytes_have_send >= mv0len)
// {
// m_iv[0].iov_len = 0;
// m_iv[1].iov_base = m_file_address + (bytes_have_send - m_write_idx);
// m_iv[1].iov_len = bytes_to_send;
// }
// else
// {
// m_iv[0].iov_base = m_write_buf + bytes_have_send;
// m_iv[0].iov_len = m_iv[0].iov_len - temp;
// }
if (bytes_to_send <= 0)
{
unmap();
modfd(m_epollfd, m_sockfd, EPOLLIN, m_TRIGMode);
if (m_linger)
{
init();
return true;
}
else
{
return false;
}
}
}
}
使用作者的wirtev后的处理方式跑,图片视屏传输正常,但是printf("2\n")没有执行过,也就是writev每次都把m_iv[0]的内容一次发送完毕,但是看作者的if(bytes_have_send >= m_iv[0].iov_len) else{}这里的else逻辑明显有问题,只是因为如上原因没有执行过,
假设writev第一次没有发出iov0的全部内容if (bytes_have_send >= m_iv[0].iov_len)不执行,则第二论的while()的if (bytes_have_send >= m_iv[0].iov_len)这里的m_iv[0].iov_len明显不是iov0的全部长度,按照博主的判断流程这里应该修改我注视的代码,不知道博主怎么认为的.
在webserver中每次需要处理完一个就绪事件才能将下一个事件放入请求队列,那这样的话就会保持请求队列始终只有一个请求,线程池的线程也只用上一个?
server: webserver.cpp:131: void WebServer::eventListen(): Assertion `ret >= 0' failed.
Aborted (core dumped)
按照Readme的步骤启动服务器,Linux下浏览器可以访问127.0.0.1:9006而Windows下不可以
环境:Ubuntu 20.04虚拟机火狐浏览器
MySQL 8.0
Windows下为客户机谷歌浏览器
如题
Line 137 in 7bd1edf
不过我手头代码版本较旧(大概一个月前吧),如果已经修复了还请秦院无视
g++ -o server main.c ./timer/lst_timer.h ./timer/lst_timer.cpp ./threadpool/threadpool.h ./http/http_conn.cpp ./http/http_conn.h ./lock/locker.h ./log/log.cpp ./log/log.h ./CGImysql/sql_connection_pool.cpp ./CGImysql/sql_connection_pool.h webserver.h webserver.cpp config.h config.cpp -lpthread -lmysqlclient
clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated]
clang: warning: treating 'c-header' input as 'c++-header' when in C++ mode, this behavior is deprecated [-Wdeprecated]
clang: warning: treating 'c-header' input as 'c++-header' when in C++ mode, this behavior is deprecated [-Wdeprecated]
clang: warning: treating 'c-header' input as 'c++-header' when in C++ mode, this behavior is deprecated [-Wdeprecated]
clang: warning: treating 'c-header' input as 'c++-header' when in C++ mode, this behavior is deprecated [-Wdeprecated]
clang: warning: treating 'c-header' input as 'c++-header' when in C++ mode, this behavior is deprecated [-Wdeprecated]
clang: warning: treating 'c-header' input as 'c++-header' when in C++ mode, this behavior is deprecated [-Wdeprecated]
clang: warning: treating 'c-header' input as 'c++-header' when in C++ mode, this behavior is deprecated [-Wdeprecated]
clang: warning: treating 'c-header' input as 'c++-header' when in C++ mode, this behavior is deprecated [-Wdeprecated]
clang: error: cannot specify -o when generating multiple output files
make: *** [server] Error 1
g++ -o ./root/CGISQL.cgi ./CGImysql/sign.cpp ./CGImysql/sql_connection_pool.cpp ./CGImysql/sql_connection_pool.h -lmysqlclient -lpthread
clang: warning: treating 'c-header' input as 'c++-header' when in C++ mode, this behavior is deprecated [-Wdeprecated]
clang: error: cannot specify -o when generating multiple output files
make: *** [CGISQL.cgi] Error 1
你好,我最近在阅读调试源码时,在Ubuntu中进行make时,系统报错 :在http_conn.cpp文件中第549行,temp=writev(m_sockfd,m_iv,m_iv_count); writev函数并没有在此文件中定义,所以make失败了,烦请大佬解释一波,不甚感激!
在centos7里面用 火狐 打开 IP:9006可以正常显示界面,但是无法播放视频(显示没有找到支持的视频格式) 可能是浏览器问题
另外在win10里以 IP:9006 无法打开界面
想问下大佬在Ubuntu底下是如何进行调试的呢?使用Clion这种IDE还是GDB?
这里是通过条件变量来实现数组大小的同步问题吧,那个异步体现在了哪里? 代码中说的是//flush_log_thread为回调函数,这里表示创建线程异步写日志,这里只是开了一个线程来运行flush_log_thread函数吧,我认为本质应该还是线程同步问题吧,这里还请解答一下
我运行成功了,可是却只能在运行server的这台计算机上访问,使用其他的计算机,输入相同的ip和端口却不能访问,有人能帮我解答下这是为什么吗,谢谢。
你好:我最近一直在学习研读调试你的Tinywebserver ,想请教一下,在http_conn.cpp文件中,有关修改数据库初始化信息,中有connection_pool *connPool=connection_pool::GetInstance("localhost", "root","root","yourdb",3306,5);这其中 “localhost” 应该输入啥? 我的开发环境是在VMware workstation 12 Pro 上安装 ubuntu16.04LTS ,服务器程序实在VMware workstation12 上的ubuntu16.04上编译的,请问此处的"localhost"应该填虚拟机ubuntu16.04的ip地址还是我笔记本的ip地址?如能帮忙解答,将不胜感激!我微信号15829468779,如能与你成为微信好友,深感荣幸!
HTTP/1.1的请求头host字段是必需的,代码貌似不符合规范
修改main.c中的数据库初始化信息一直报错
比如http_conn类中的bytes_to_send 字段,在写线程和读线程中都有用到,但时并未加锁,我觉得是有线程安全问题的。
bool dealwithsignal(bool timeout, bool& stop_server);
是不是应该改成
bool dealwithsignal(bool &timeout, bool& stop_server);
当一个write()或read_once()阻塞时,webserver是否就会被阻塞在 这一步无法处理下一个请求和新的就绪事件
大佬,传输大文件时,一次传输的最大上限是多少?一次传输多少才需要二次传输?这个怎么计算?希望大佬可以讲解。
目前学完了C++ 基本功,和基本的多线程编程知识,想了解一下如果想跟得上这个项目,需要储备什么知识呢?
光看游双那本书够吗?
请大家指点一下~
//pop时,如果当前队列没有元素,将会等待条件变量
bool pop(T &item)
{
m_mutex.lock();
while (m_size <= 0)
{
// 这里若线程wait成功,函数返回0
if (!m_cond.wait(m_mutex.get()))
{
m_mutex.unlock();
return false;
}
}
m_front = (m_front + 1) % m_max_size;
item = m_array[m_front];
m_size--;
m_mutex.unlock();
return true;
}
这是源码中block_queue中的pop函数,wait那一行是不是存在逻辑错误?
而在微信公众号解析代码中:if (0 != pthread_cond_wait(m_cond, m_mutex)) ,两者有出入
大家在运行项目时遇到问题,优先查阅本lssue。
如果本issue不能解决你的问题,欢迎盖楼或直接公号私信我,我会尽快回复。
请问readme中的QPS是在什么硬件条件下测试的?
另外有在云服务器上测试过QPS吗?(一般都是1核cpu配置)
想参考一下数据,谢谢!
请问有cmakelists文件吗,我根据makefile写的cmakelists但是运行后不能进入,命令行上一直显示close17 close16
我发现使用 writev 向 socket 写数据时,如果没有一次写完,就需要调整 iov 数组,不然图片会显示不完整。
我是在虚拟机上启动 server,然后在实体机上请求图片的,这时候 writev 会连续写几次才能写完,这时候就会出问题(图片显示不完整)。而在本地(同样在虚拟机中)请求图片的话,writev 可以一次性写完,图片可以完整的显示出来。
我自己的代码如下:
/* 写 HTTP 响应 */
bool http_conn::write() {
int tmp = 0;
printf("---debug---%d bytes to send\n", __bytes_to_send);
if (__bytes_to_send == 0) {
modfd(epollfd, __sockfd, EPOLLIN);
__init();
return true;
}
while (1) {
tmp = Writev(__sockfd, __iv, __iv_cnt);
if (tmp < 0) {
if (errno == EAGAIN) {
/* 若写缓冲区没有空间,则等待缓冲区可写,在此期间无法接收客户端请求 */
modfd(epollfd, __sockfd, EPOLLOUT);
return true;
}
__unmap();
return false;
}
printf("---debug---sent %d bytes\n", tmp);
__bytes_to_send -= tmp;
__bytes_have_sent += tmp;
__adjust_iv();
if (__bytes_to_send <= 0) {
__unmap();
/* HTTP 响应发送成功,根据 Connection 字段决定是否立即关闭连接 */
if (__linger) {
__init();
modfd(epollfd, __sockfd, EPOLLIN);
return true;
} else {
modfd(epollfd, __sockfd, EPOLLIN);
return false;
}
}
}
return false;
}
___adjust_iv 函数:
/* 每次调用 writev 都需要调整 __iv */
void http_conn::__adjust_iv() {
if (__bytes_have_sent >= __write_idx) {
__iv[0].iov_len = 0;
__iv[1].iov_base = __file_addr + (__bytes_have_sent - __write_idx);
__iv[1].iov_len = __bytes_to_send;
} else {
__iv[0].iov_base = __write_buf + __bytes_have_sent;
__iv[0].iov_len = __write_idx - __bytes_have_sent;
}
}
https://github.com/qinguoyi/TinyWebServer/blob/master/http/http_conn.cpp#L426
user’s inputs are directly spliced into the SQL statement
Attack vector:server supports the http protocol, capture the packet in the registration interface, and modify the packet to a malicious statement.
https://github.com/qinguoyi/TinyWebServer/blob/master/http/http_conn.cpp#L425
Because the length of the sql statement is not limited, the variable sql_insert
overflows. The memory storing sql_insert
is called later, causing the program to crash.
https://github.com/qinguoyi/TinyWebServer/blob/master/http/http_conn.cpp#L410
The program does not limit the length of the input of variable name and variable password.Users can enter characters of any length to cause stack overflow
void http_conn::process()
{
HTTP_CODE read_ret = process_read();
if (read_ret == NO_REQUEST)
{
modfd(m_epollfd, m_sockfd, EPOLLIN, m_TRIGMode);
return;
}
bool write_ret = process_write(read_ret); //如果返回false,close_conn()就会执行(m_sockfd=-1),连接关闭,然后还要注册写事件?
if (!write_ret)
{
close_conn();
}
modfd(m_epollfd, m_sockfd, EPOLLOUT, m_TRIGMode);
}
前辈你好:
http_conn.c 文件的users(就是用户的map),是不是应该设置成staic类型的。如果是非static类型的,每次来一个链接,就应该从数据库拷贝一次用户名和密码表,但http_conn::init()函数没有进行这一操作,webserver.c也只是拷贝了一次。另外,微信群怎么加入啊,希望和大家一起讨论。
cgi文件是怎么定义的,通过什么函数或方法接收前端传过来的用户数据?
TinyWebServer/http/http_conn.cpp
Line 734 in 57d022f
m_iv[0].iov_base = m_write_buf + bytes_hvae_send;
吗? 不是应该加上已经发送的字节数吗?还是我理解错了?请问下,Readme步骤都没错. 我现在是浏览器输入什么内容 实现 前后端运行效果呀? localhost 和 端口号 是根据什么进行设置的 还是啥? 有人知道吗?
博主你写的项目很详细很易懂,醍醐灌顶。迫不及待等你的新文章。希望博主快快更新!^-^
第一篇解说资源访问不了,,??
http_conn.h和http_conn.cpp中,如果read_once函数读取的数据跨越了前一个请求和后一个请求的HTTP报文,那么在调用write函数在某些条件下,调用了init()函数,清空了读缓冲区,那么后一个请求的一部分数据不就丢失了?
有没有小伙伴遇到这个问题呀,不会解决
前辈你好,我有几个疑问
1.webserver类中定义了一个sort_timer_lst变量timer_lst,代码中操作的也都是变量timer_lst。但是最后在eventloop函数使用了utils.timer_hander()函数。utils对象的初始化使用的是最开始定义的timer_lst,后面utils对象的m_timer_lst没有进行更新.
我觉得是不是把utils对象的初始化放在webserver类的构造函数,后面统一对utils.m_timer_lst操作。要么就是改eventloop中的代码。
2.
//处理新到的客户连接
if (sockfd == m_listenfd)
{
bool flag = dealclinetdata();
if (false == flag)//?????
continue;
}
这里的if判断条件是什么作用呢?我猜测是不是你想在flag==false的情况下输出日志,代码未完成吗?感谢解答
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.