# 创建HTTP服务器

建议首选阅读官方文档[Http\Server](https://wiki.swoole.com/wiki/page/326.html)章节

* 一、http\_server简介
* 二、创建http\_server
* 三、swoole\_http\_request
* 四、swoole\_http\_response
* 五、配置介绍（查看官方文档:[配置选项](https://wiki.swoole.com/wiki/page/620.html) ，[常见问题](https://wiki.swoole.com/wiki/page/431.html)）
* 六、nginx+swoole (可查看左侧响应章节)
* 七、多端口监听
* 八、其他： 示例

## 一、http\_server简介

swoole 内置实现了一个简单的httpServer类。swoole版的http server相对于php-fpm，最大优势在于高性能,代码一次载入内存，后续无需再解释执行，但是swoole\_http\_server对Http协议的支持并不完整，实际生产环境，一般是前面加一层Nginx，由Nginx解析一些静态css、js文件，php文件请求交由swoole处理

示意图：

![](/files/-LfnTGVFv76Mt6RJ7GEX)

* 1、http\_server本质是swoole\_server,不过在协议的解析部分固定使用的是http协议解析
* 2、完整的http协议请求会被解析并封装在swoole\_http\_request对象当中
* 3、所有的http响应都通过swoole\_http\_response对象进行封装和发送

## 二、创建http\_server

使用swoole，通过几行代码即可写出一个异步非阻塞多进程的Http服务器

```php
$http=new \swoole\http\server('0.0.0.0',9501);
$http->on('request',function ($request,$response){
    $response->end('发送数给客户端');
});

$http->start();
```

其中onRequest回调接收两个参数分别是swoole\_http\_request对象和swoole\_http\_response对象，分别负责request请求和response响应。

## 三、swoole\_http\_request

swoole\_http\_request，负责http请求的相关信息。我们可以在这个对象上，获取header\server\get\post\files\cookie等信息，这等同于php的超全局变量，但是这可不是超全局的。

```php
$_HEADER = $request->header;
$_SERVER = $request->server;
$_GET =$request->get;
$_POST = $request->post;
$_COOKIE = $request->cookie;
$_FILES = $request->files;
$_CONTENT = request->rawContent;
$request->getData;
```

注意事项：

1、Swoole的HttpServer可以接受application/x-www-form-urlencoded/form-data类型的POST参数，并且会将解析后的参数存放在swoole\_server\_request对象的post成员变量内。

对于application/json或者其他类型的请求参数，Swoole底层并不会自动解析。但是Swoole的swoole\_server\_request提供了rawContent方法可以获得原始的POST字符串,我们可以根据Content-type类型做相应的解析。

2、POST/文件上传需要设置临时文件位置（upload\_tmp\_dir），并且需要设置包的大小，最大尺寸受到 package\_max\_length 配置项限制，默认为2M，调用$response->end后会自动删除，在end之后操作上传文件会抛出文件不存在错误。

## 四、swoole\_http\_response

swoole\_http\_response，负责处理HTTP响应信息，包括响应的头信息header\响应状态等,跟传统的HTTP请求和响应差别不大，比较简单，大概了解下即可。

具体方法如下：

```php
Http\Response->header
Http\Response->cookie
Http\Response->status
Http\Response->gzip
Http\Response->redirect
Http\Response->write
Http\Response->sendfile
Http\Response->end
Http\Response->detach
Http\Response::create
```

> 注意事项：\
> 请在end()之前设置相应的响应头、状态等等，end操作后将向客户端浏览器发送内容，并销毁request/response对象

## 七、多端口监听

在实际运用场景中，服务器可能需要监听不同host下的不同端口。比如，一个应用服务器，可能需要监听外网的服务端口，同时也需要监听内网的管理端口。在Swoole中，可以轻松的实现这样的功能。 Swoole提供了addlistener函数用于给服务器添加一个需要监听的host及port。关于函数的介绍官方文档已经说的比较清楚：[多端口监听的使用](https://wiki.swoole.com/wiki/page/161.html)

示例

server.php

```php
<?php

//创建Server对象，监听 0.0.0.0:9501端口
$serv = new swoole_server("0.0.0.0", 9502,SWOOLE_PROCESS,SWOOLE_SOCK_TCP);

$serv->addlistener('127.0.0.1',9503,SWOOLE_SOCK_TCP);

//配置
$serv->set(array(
    'worker_num' =>5, //设置工作进程
    'reactor_num'=>6, //线程组个数,最大不得超过cpu*4
    'max_request'=>1000,
    'package_max_length '=>1024*1024*3,
//    'open_length_check' => true,
//    'package_length_type'=>'N',
//    'package_length_offset'=>0, //计算总长度
//    'package_body_offset'=>4,//包体位置
//    'package_max_length'=>1024*1024*3 //总的请求数据大小字节为单位
));

//监听连接进入事件,有客户端连接进来的时候会触发
$serv->on('connect', function ($serv,$fd,$from_id) {

});

//监听数据接收事件,server接收到客户端的数据后，worker进程内触发该回调
$serv->on('receive', function ($serv, $fd, $from_id, $data) {

     $info=$serv->connection_info($fd);

     //区分内网外网
     if($info['server_port']){

     }
});
```

注意:

* 1.如果是http协议,不能绑定多个http协议监听
* 2.如果要启用新的协议监听,必须单独调用set方法设置新的协议才会启用新协议
* 3.只有同种协议才会触发相同事件

示例

```php
<?php

//根据端口跟ip地址划分业务,内网外网
$http=new \swoole\http\server('0.0.0.0',9502);

$port1=$http->addlistener('127.0.0.1',9503,SWOOLE_TCP);

//启用新协议
$port1->set([
    'package_max_length'=>1024*1024*10,
]);

$http->set([
    'package_max_length'=>1024*1024*10,
    'upload_tmp_dir'=>__DIR__.'/upload'
]);



//监听http协议
$http->on('request',function ($request,$response){

    var_dump('http');

//$response->end('<meta charset="UTF-8"><h2>呵呵</h2>'); //返回请求

});

//
////为端口1绑定回调
$port1->on('receive',function ($request,$response){

    var_dump('tcp');

//$response->end('<meta charset="UTF-8"><h2>六星教育</h2>'); //返回请求

});

$http->start();
```

## 八、其他示例

```php
<?php
$http=new \swoole\http\server('0.0.0.0',9502);

$http->set([
    'package_max_length'=>1024*1024*10,
    'upload_tmp_dir'=>__DIR__.'/upload'
]);

//监听http协议
$http->on('request',function ($request,$response){

     //var_dump($request->get);
     //var_dump($request->server);

     //var_dump($request->header);
     // $response->end('发送数据给客户端');
     // var_dump('我是post',$request->post);

    //post
     //var_dump($request->rawContent()); //获取原始数据 php://input

    //根据请求头的不同类型,返回相应格式的数据
    if(isset($request->header['content-type']) && $request->header['content-type']=='application/json'){
        var_dump('接收到json格式数据');
         //json_encode();
    }elseif(isset($request->header['content-type']) && $request->header['content-type']=='application/xml'){

    }

    //文件上传
    //$file=$request->files;
   //move_uploaded_file($file['peterFile']['tmp_name'],__DIR__.'/upload/1.txt');
    //设置响应头
//    $response->header('Content-Type','text/html');
//    $response->header('Charset','utf-8');
//
//    $response->status(123);
//
//    $response->cookie('user','peter');
//
//    $response->write('123---'); //分段发送不能使用end
//    $response->write('456'); //分段发送不能使用end
//
//    $response->end('<meta charset="UTF-8"><h2>六星教育</h2>'); //返回请求
    //$response->header('Content-Type', 'image/jpeg');
    //$response->sendfile(__DIR__.'/upload/1.txt');


});

$http->start();
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://xiaoxiami.gitbook.io/swoole/swoole-ji-chu/wang-luo-tong-xin-yin-qing/chuang-jian-http-fu-wu.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
