简单http学习:5 excute_cgi调用

void execute_cgi(int client, const char *path,
                 const char *method, const char *query_string)
{
  char buf[1024];
  int cgi_output[2];
  int cgi_input[2];
  pid_t pid;
  int status;
  int i;
  char c;
  int numchars = 1;
  int content_length = -1;

  buf[0] = 'A';
  buf[1] = '\0';
  //保证进入
  if (strcasecmp(method, "GET") == 0)//如果是get,则直接丢弃?
    while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */
      numchars = get_line(client, buf, sizeof(buf));
  else /* POST */
  {
    numchars = get_line(client, buf, sizeof(buf));
    while ((numchars > 0) && strcmp("\n", buf))//如果没到结束一直读
    {
      buf[15] = '\0';
      if (strcasecmp(buf, "Content-Length:") == 0)
        content_length = atoi(&(buf[16]));//找到content-length长度
      numchars = get_line(client, buf, sizeof(buf));
    }
    if (content_length == -1)//如果为-1,错误请求
    {
      bad_request(client);//返回400
      return;
    }
  }
  //开始写
  sprintf(buf, "HTTP/1.0 200 OK\r\n");
  send(client, buf, strlen(buf), 0);

//#include<unistd.h>
//int pipe(int filedes[2]);
//返回值:成功,返回0,否则返回-1。参数数组包含pipe使用的两个文件的描述符。fd[0]:读管道,fd[1]:写管道。
//必须在fork()中调用pipe(),否则子进程不会继承文件描述符。
//两个进程不共享祖先进程,就不能使用pipe。但是可以使用命名管道。


  if (pipe(cgi_output) < 0)
  {
    cannot_execute(client);//错误代码500
    return;
  }
  if (pipe(cgi_input) < 0)
  {
    cannot_execute(client);
    return;
  }
  //成功建立管道
  if ((pid = fork()) < 0)
  {//子进程建立失败
    cannot_execute(client);
    return;
  }
  //进入子进程
  if (pid == 0) /* child: CGI script */
  {
    char meth_env[255];//设置request_method 的环境变量
    char query_env[255];//GET 的话设置 query_string 的环境变量
    char length_env[255];//POST 的话设置 content_length 的环境变量
    //标准输入文件的文件描述符:0
    //标准输出文件的文件描述符:1
    //标准错误输出的文件描述符:2

    //dup2创建一个newfd,newfd指向oldfd的位置
    dup2(cgi_output[1], 1);//这就是将标准输出重定向到output管道的写入端,也就是输出内容将会输出到output写入
    dup2(cgi_input[0], 0);//将标准输入重定向到input读取端,也就是将从input[0]读内容到input缓冲
    close(cgi_output[0]);//关闭output管道的的读取端
    close(cgi_input[1]);//关闭input管道的写入端
    sprintf(meth_env, "REQUEST_METHOD=%s", method);//把method保存到环境变量中
    //函数说明:int putenv(const char * string)用来改变或增加环境变量的内容.
    //如果该环境变量原先存在, 则变量内容会依参数string 改变, 否则此参数内容会成为新的环境变量.
    //返回值:执行成功则返回0, 有错误发生则返回-1.
    putenv(meth_env);
    if (strcasecmp(method, "GET") == 0)//如果是get
    {
      sprintf(query_env, "QUERY_STRING=%s", query_string);//存储query_string到query_env
      putenv(query_env);
    }
    else
    { /* POST */
      sprintf(length_env, "CONTENT_LENGTH=%d", content_length);//存储tontent_length到length_env
      putenv(length_env);
    }
    // 表头文件#include<unistd.h>
    // int execl(const char * path,const char * arg,....);
    // 函数说明:  execl()用来执行参数path字符串所代表的文件路径,接下来的参数代表执行该文件时传递过去的argv(0)、argv[1]……,最后一个参数必须用空指针(NULL)作结束。
    // 返回值:    如果执行成功则函数不会返回,执行失败则直接返回-1
    execl(path, path, NULL);//执行path出的脚本
    exit(0);//退出
  }


  else
  { /* parent */
    close(cgi_output[1]);//关闭output的写入
    close(cgi_input[0]);//关闭input的读取
    if (strcasecmp(method, "POST") == 0)//如果是post
      for (i = 0; i < content_length; i++)
      {
        recv(client, &c, 1, 0);//一个字节一个字节读取
        write(cgi_input[1], &c, 1);//写入到input的写入
      }
    //从input写入后,进入子进程,子进程调用excel执行

    //依次发送到客户端
    while (read(cgi_output[0], &c, 1) > 0)
      send(client, &c, 1, 0);

    close(cgi_output[0]);//ouput的读
    close(cgi_input[1]);//关闭input的写
    waitpid(pid, &status, 0);//等待子进程中止
    //定义函数:pid_t waitpid(pid_t pid, int * status, int options);
    //函数说明:wait()会暂时停止目前进程的执行, 直到有信号来到或子进程结束. 
    //waitpid不会阻塞
    //如果不在意结束状态值, 则参数status 可以设成NULL. 参数pid 为欲等待的子进程识别码, 其他数值意义如下:
    //1、pid<-1 等待一个指定进程组中的任何子进程,这个进程组的ID等于pid的绝对值
    //2、pid=-1 等待任何子进程, 相当于wait().
    //3、pid=0 等待进程组识别码与目前进程相同的任何子进程.
    //4、pid>0 等待任何子进程识别码为pid 的子进程.
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您解答关于Java调用企业微信上传临时素材获取media_id的问题。 首先,您需要准备好以下信息: 1. 企业微信的CorpID和Secret。 2. 上传的临时素材文件,可以是图片、音频、视频等。 3. 文件的类型,例如:image、voice、video等。 然后,您可以按照以下步骤进行操作: 1. 构造请求URL:https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE 其中,ACCESS_TOKEN是企业微信的接口调用凭证,可以通过企业微信的API获取;TYPE是上传的临时素材的类型。 2. 发送HTTP POST请求,上传临时素材文件。 3. 解析返回结果。如果上传成功,返回的JSON数据中会包含media_id字段,该字段即为上传的临时素材的media_id。 以下是一个Java调用企业微信上传临时素材获取media_id的示例代码: ``` public String uploadTempMedia(String filePath, String type, String accessToken) { String result = null; File file = new File(filePath); String url = "https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token=" + accessToken + "&type=" + type; try { CloseableHttpClient httpClient = HttpClients.createDefault(); HttpPost httpPost = new HttpPost(url); httpPost.setHeader("Connection", "Keep-Alive"); httpPost.setHeader("Cache-Control", "no-cache"); MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); builder.addBinaryBody("media", file, ContentType.DEFAULT_BINARY, file.getName()); HttpEntity entity = builder.build(); httpPost.setEntity(entity); CloseableHttpResponse response = httpClient.execute(httpPost); try { HttpEntity responseEntity = response.getEntity(); if (responseEntity != null) { String responseStr = EntityUtils.toString(responseEntity, "UTF-8"); JSONObject jsonObject = JSONObject.fromObject(responseStr); result = jsonObject.getString("media_id"); } } finally { response.close(); } } catch (Exception e) { e.printStackTrace(); } return result; } ``` 您只需要将filePath、type、accessToken三个参数替换成您自己的值,即可使用该方法上传临时素材并获取media_id。 希望这个回答能够帮到您!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值