<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Http on Jsj&#39;s Blog</title>
    <link>https://hahamaker.top/tags/http/</link>
    <description>Recent content in Http on Jsj&#39;s Blog</description>
    <generator>Hugo</generator>
    <language>zh-cn</language>
    <lastBuildDate>Sun, 13 Oct 2019 22:46:48 +0800</lastBuildDate>
    <atom:link href="https://hahamaker.top/tags/http/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Tinyhttpd学习</title>
      <link>https://hahamaker.top/posts/tinyhttpd_learn/</link>
      <pubDate>Sun, 13 Oct 2019 22:46:48 +0800</pubDate>
      <guid>https://hahamaker.top/posts/tinyhttpd_learn/</guid>
      <description>&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;第一次的源代码阅读, 可能解释的不是很好, tinyhttpd网上都说是一个不错的学习源代码的例子， 所以就用这个上手了。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://sourceforge.net/projects/tiny-httpd/&#34;&gt;tinyhttpd官方源码在这里下载&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/jiaoshijie/misc_code/tree/main/c-like/tinyhttpd&#34;&gt;我的代码在这里&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;一些改动:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;将cgi程序由perl语言改为python3&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;函数说明&#34;&gt;函数说明&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;startup() 初始化服务端套接字, 如果端口号没有指定，则使用随机的端口号&lt;/li&gt;
&lt;li&gt;error_die() 打印服务端启动过程中的错误信息, 并退出程序&lt;/li&gt;
&lt;li&gt;accept_request() 处理客户端请求
&lt;ul&gt;
&lt;li&gt;获取请求类型(&lt;code&gt;GET&lt;/code&gt; or &lt;code&gt;POST&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;获取客户端要的网页文件的路径&lt;/li&gt;
&lt;li&gt;使用stat()函数获取文件属性，判断是执行cgi还是发送普通网页&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;get_line() 获取网络字符串的一行(换行符为: &lt;code&gt;\r\n&lt;/code&gt; )&lt;/li&gt;
&lt;li&gt;unimplemented() 客户端请求不正确时(服务器不支持的请求)，发送给客户端&lt;a href=&#34;https://man.ilovefishc.com/pageHTML5/HTTP.html&#34;&gt;501&lt;/a&gt;错误&lt;/li&gt;
&lt;li&gt;not_found_file() 客户端请求网页内容不存在返回该函数404&lt;/li&gt;
&lt;li&gt;cannot_execute() 不能执行cgi文件&lt;/li&gt;
&lt;li&gt;bad_request() 客户端请求错误&lt;/li&gt;
&lt;li&gt;serve_file() 发送网页文件到客户端&lt;/li&gt;
&lt;li&gt;execute_cgi() 执行cgi文件并将结果发送到客户端&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt=&#34;tinyhttpd_01&#34; loading=&#34;lazy&#34; src=&#34;../../images/tinyhttpd_01.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;cgi介绍&#34;&gt;cgi介绍&lt;/h2&gt;
&lt;p&gt;cgi(Common Gateway Interface)规定Web服务器调用其他程序的接口协议(就是如何调用程序， 传递参数， 输出结果), &lt;a href=&#34;https://blog.csdn.net/xiaominthere/article/details/32328589&#34;&gt;详细的cgi简介&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;cgi接口使用标准输入、标准输出和环境变量来交换数据&lt;/p&gt;
&lt;p&gt;该程序中使用的环境变量:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;REQUEST_METHOD&lt;/code&gt;: 浏览器请求方法&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CONTENT_LENGTH&lt;/code&gt;: post请求时的form表单的内容长度&lt;/li&gt;
&lt;li&gt;&lt;code&gt;QUERY_STRING&lt;/code&gt;: get请求时form表单的内容放到该环境变量中&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;cgi从标准输入中获取数据，把数据输出到标准输出&lt;/p&gt;
&lt;p&gt;&lt;img alt=&#34;tinyhttpd_02&#34; loading=&#34;lazy&#34; src=&#34;../../images/tinyhttpd_02.png&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;linux系统函数&#34;&gt;Linux系统函数&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;pipe()进程见通信的一种实现方法
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// file_pipe[0] 为读取端(输出端), file_pipe[1]为写入端(输入端)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file_pipe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;pipe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;file_pipe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;fork()创建线程函数
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ipid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;fork&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;// 创建线程
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ipid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// 子线程
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// 主线程
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;dup2()重定向一个文件描述符
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;* stdin:0, stdout:1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;* 下面两句将重定向stdin和stdout到file[0], 和file[1]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;dup2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;dup2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;putenv()设置环境变量(只在该进程中生效)&lt;/li&gt;
&lt;li&gt;execl()在该进程中执行外部程序
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 程序绝对路径 程序名称 参数 目标 NULL
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;execl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;/bin/ls&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;ls&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;-al&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;/etc/passwd&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;Notes: 该函数执行时，会用这个新的进程替代当前进程就是该函数执行完后，就会退出整个进程，而不会执行下面的代码, 所以通常使用子线程执行该函数&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
  </channel>
</rss>
