关于URL

URL(Uniform Resource Locator) 地址用于描述一个网络上的资源, 基本格式如下

schema://host[:port#]/path/.../[;url-params][?query-string][#anchor]

  • scheme 指定低层使用的协议(例如:http, https, ftp)
  • host HTTP服务器的IP地址或者域名
  • port# HTTP服务器的默认端口是80,这种情况下端口号可以省略。如果使用了别的端口,必须指明,例如 http://www.cnblogs.com:8080/
  • path 访问资源的路径
  • url-params
  • query-string 发送给http服务器的数据
  • anchor- 锚
URL实例
http://www.mywebsite.com/sj/test;id=8079?name=sviergn&x=true#stuffSchema: http
host: www.mywebsite.com
path: /sj/test
URL params: id=8079
Query String: name=sviergn&x=true
Anchor: stuff

http消息的结构

HTTP Request 消息分为3部分

Name content
requset line METHOD /path-to-resource HTTP/version-number
http header Header-Name-1:value
Header-Name-2:value
......
blank line
body Optional request body
request line实例

GET http://cn.bing.com/sa/8_01_0_000000/HpbHeaderPopup.js HTTP/1.1

http header实例
Host: cn.bing.com
Proxy-Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
Accept: */*
Referer: http://cn.bing.com/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8
body实例

{"id":130970,"cateId":"1002"} 注:GET方法是没有body的

关于METHOD中POST和GET方法的区别
  1. GET提交的数据会放在URL之后,以?分割URL和传输数据,参数之间以&相连,如EditPosts.aspx?name=test1&id=123456. POST方法是把提交的数据放在HTTP包的Body中.
  2. GET提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制.
  3. GET方式需要使用Request.QueryString来取得变量的值,而POST方式通过Request.Form来获取变量的值.
  4. GET方式提交数据,会带来安全问题,比如一个登录页面,通过GET方式提交数据时,用户名和密码将出现在URL上,如果页面可以被缓存或者其他人可以访问这台机器,就可以从历史记录获得该用户的账号和密码.

HTTP Response消息也分为三部分

Name content
response line HTTP/version-number status_code message
http header Header-Name-1:value
Header-Name-2:value
......
blank line
body Optional response body

Response 消息中的第一行叫做状态行,由HTTP协议版本号, 状态码, 状态消息 三部分组成。状态码用来告诉HTTP客户端,HTTP服务器是否产生了预期的Response.

  • HTTP/1.1中定义了5类状态码, 状态码由三位数字组成,第一个数字定义了响应的类别

    • 1XX 提示信息 - 表示请求已被成功接收,继续处理
    • 2XX 成功 - 表示请求已被成功接收,理解,接受
    • 3XX 重定向 - 要完成请求必须进行更进一步的处理
    • 4XX 客户端错误 - 请求有语法错误或请求无法实现
    • 5XX 服务器端错误 - 服务器未能实现合法的请求

关于getopt getopt_long参数处理函数

简述

在程序中一般都会用到命令行选项,我们可以使用getopt和getopt_long函数来解析命令行参数

getopt

getopt主要用于处理短命令行选项,例如 ./test -v 中-v就是一个短命令行选项。
使用该函数需要引入头文件<unistd.h>,以下是getopt函数的定义

#include <unistd.h>
extern char *optarg;  //选项的参数指针,存放选项对应的输入参数
extern int optind;   //下一次调用getopt时,从optind存储的位置处重新开始检查选项。
extern int opterr;  //当opterr=0时,getopt不向stderr输出错误信息。
extern int optopt;  //当命令行选项字符不包括在optstring中或者最后一个选项缺少必要的参数时,该选项存储在optopt中,getopt返回'?’int getopt(int argc, char * const argv[], const char * optstring);

其中argc和argv是main函数中传递参数和内容,optstring用来指定可以处理哪些选项,
字符串optstring可以下列元素

  1. 单个字符,表示选项,没有参数,optarg=NULL.
  2. 单个字符后接一个冒号:表示该选项后必须跟一个参数。参数紧跟在选项后或者以空格隔开。该参数的指针赋给optarg。
  3. 单个字符后跟两个冒号,表示该选项后必须跟一个参数。参数必须紧跟在选项后不能以空格隔开。该参数的指针赋给optarg。(这个特性是GNU的扩张)。
    下面是optstring的一个实例:

    "a:bc::"

该示例表明程序可以接受三个选项:-a -b -c,其中a后面的:表示该选项后面要跟一个参数,例如./test -a text的形式,c后面的::表示该选项后面要跟一个参数且中间不准有空格,例如./test -ctext,选项后面跟的参数会被保存到optarg变量中。下面一段代码是该函数的使用实例

#include <stdio.h>
#include <unistd.h>int main(int argc,char * argv[])
{int ch;while((ch = getopt(argc, argv, "a:bc::")) != -1){switch (ch) {case 'a':printf("option a: %s\n",optarg);break;case 'b':printf("option b: %s\n",optarg);break;case 'c':printf("option c: %s\n",optarg);break;case 'd':printf("unknown option\n");break;default:printf("unknown option\n");break;}}return 0;
}

getopt_long

getopt_long() 是同时支持长选项和短选项的 getopt() 版本。它可以根据输入的option是单横线还是双横线开头来区分是短选项还是长选项。
以下是getopt_long的声明:

#include <getopt.h>
struct option{    //长选项表const char *name; //选项名,前面没有短横线,help,verbose之类int has_arg;      //描述选项是否需要选项参数,no_argument 0 表示选项没有参数,required_argument 1 表示需要参数,optional_argument 2 选项参数可选int *flag;  //如果这个指针为NULL,那么getopt_long()返回该结构val字段中的数值。如果该指针不为NULL,getopt_long()会使得它所指向的变量中填入val字段中的数值,并且getopt_long()返回0int val;
};
// 每个长选项在长选项表中都有一个单独条目,该条目里需要填入正确的数值。数组中最后的元素的值应该全是0。数组不需要排序,getopt_long()会进行线性搜索。
int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);

在webbench.c中充分体现了对getopt_long的使用

#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
#include <stdlib.h>#define METHOD_GET 0
#define METHOD_POST 1
#define METHOD_OPTIONS 2
#define METHOD_TRACE 3
#define PROGRAM_VERSION "0.1"int port = 80;
int benchtime = 0;
int http10 = 0;
int clients = 0;
int method = 0;
int force = 0;
int force_reload = 0;static const struct option longopts[]=
{{"force",no_argument,&force,1},{"reload",no_argument,&force_reload,1},{"time",required_argument,NULL,'t'},{"help",no_argument,NULL,'?'},{"http09",no_argument,NULL,'9'},{"http10",no_argument,NULL,'1'},{"http11",no_argument,NULL,'2'},{"get",no_argument,&method,METHOD_GET},{"post",no_argument,&method,METHOD_POST},{"options",no_argument,&method,METHOD_OPTIONS},{"trace",no_argument,&method,METHOD_TRACE},{"version",no_argument,NULL,'V'},{"port",required_argument,NULL,'p'},{"clients",required_argument,NULL,'c'},{"NULL",0,NULL,0}
};static void usage()
{fprintf(stderr,"damo [option]... URL\n""  -f|--force              Don't wait for reply from server.\n""  -r|--reload             Send reload request - Pragma: no-cache.\n""  -t|--time <sec>         Run benchmark for <sec> seconds.Default 30.\n""  -p|--port <server:port> Set server port for request.\n""  -c|--clients <n>        Run <n> HTTP clients at once.Default one.\n""  -9|--http09             Use HTTP/0.9 style requests.\n""  -1|--http10             Use HTTP/1.0 protocol.\n""  -2|--http11             Use HTTP/1.1 protocol.\n""  --get                   Use GET request method.\n""  --head                  Use HEAD request method.\n""  --options               Use OPTIONS request method.\n""  --trace                 Use TRACE request method.\n""  -?|-h|--help            This information.\n""  -V|--version            Display program version.\n");
}int main(int argc,char *argv[])
{int options_index = 0;int opt = 0;if(argc == 1){usage();return 2;}while((opt = getopt_long(argc,argv,"912Vfrt:p:c:?h",longopts,&options_index)) != EOF){switch(opt){case  0 :  break;case 'f':  force = 1; printf("I choose f\n");break;case 'r':  force_reload = 1;break;case '9':  http10 = 0;break;case '1':  http10 = 1;break;case '2':  http10 = 2;break;case 'V':printf(PROGRAM_VERSION"\n");exit(0);case 't':benchtime = atoi(optarg);break;case 'h':case '?':usage();return 2;break;case 'c':  clients = atoi(optarg);break;case 'p':  port = atoi(optarg);break;}}
}

关于网络IPC:套接字

此部分基本参考APUE,有兴趣可以看看这本书

网络进程间通信:socket API简介

不同计算机(通过网络相连)上运行的进程相互通信机制称为网络进程间通信(network IPC)。

在本地可以通过进程PID来唯一标识一个进程,但是在网络中这是行不通的。其实TCP/IP协议族已经帮我们解决了这个问题,网络层的“ip地址”可以唯一标识网络中的主机,而传输层的“协议+端口”可以唯一标识主机中的应用程序(进程)。这样利用三元组(ip地址,协议,端口)构成套接字,就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互。

几个定义

  1. IP地址:即依照TCP/IP协议分配给本地主机的网络地址,两个进程要通讯,任一进程首先要知道通讯对方的位置,即对方的IP。
  2. 端口号:用来辨别本地通讯进程,一个本地的进程在通讯时均会占用一个端口号,不同的进程端口号不同,因此在通讯前必须要分配一个没有被访问的端口号。
  3. 连接:指两个进程间的通讯链路。
  4. 半相关:网络中用一个三元组可以在全局唯一标志一个进程:(协议,本地地址,本地端口号)这样一个三元组,叫做一个半相关,它指定连接的每半部分。
  5. 全相关:一个完整的网间进程通信需要由两个进程组成,并且只能使用同一种高层协议。也就是说,不可能通信的一端用TCP协议,而另一端用UDP协议。因此一个完整的网间通信需要一个五元组来标识:(协议,本地地址,本地端口号,远地地址,远地端口号),这样一个五元组,叫做一个相关(association),即两个协议相同的半相关才能组合成一个合适的相关,或完全指定组成一连接。

套接字描述符

套接字是端点的抽象。与应用进程要使用文件描述符访问文件一样,访问套接字也需要用套接字描述符。套接字描述符在UNIX系统中是用文件描述符实现的。

要创建一个套接字,可以调用socket函数。

#include <sys/socket.h>
int socket(int domain, int type, int protocol);
参数 类型
domain:socket通信域 AF_INET IPV4 默认 IPPROTO_TCP 因特网域
AF_INET6 IPV6因特网域
AF_UNIX UNIX域 同 AF_LOCAL
AF_UNSPEC 未指定
type: socket类型 SOCK_STREAM 有序,可靠,双向的面向连接字节流 在AF_INET域中默认IPPROTO_TCP
SOCK_DGRAM 长度固定的,无连接的不可靠报文传递 在AF_INET域中默认IPPROTO_UDP
SOCK_RAW IP协议的数据包接口(POSIX1中为可选)
SOCK_SEQPACKET 长度固定有序可靠地面向连接的报文传递
protocol:指定协议 IPPROTO_TCP TCP传输协议
IPPROTO_UDP UDP传输协议
IPPROTO_ICMP
IPPROTO_IP
IPPROTO_IPV6
IPPROTO_RAW 原始IP数据包协议

地址格式

#include <netinet/in.h>
struct in_addr {in_addr_t       s_addr; //IPV4 address
};struct sockaddr_in {sa_family_t     sin_family; // address familyin_port_t       sin_port;   // port numberstruct in_addr  sin_addr;   // IPV4 address
};
将套接字和地址绑定

此段内容与源码关系不大,仅作了解即可
与客户端的套接字关联的地址意义不大,可以让系统选择一个默认的地址。然而,对于服务器,需要给一个接收客户端请求的套接字绑定一个众所周知的地址。客户端应有一种方法用以连接服务器的地址,最简单的方法就是为服务器保留一个地址并且在/etc/services或某个名字服务(name service)中注册。

#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

参数:

  • 第一个参数:bind()函数把一个地址族中的特定地址赋给该sockfd(套接字描述字)。例如对应AF_INET、AF_INET6就是把一个ipv4或ipv6地址和端口号组合赋给socket。
  • struct sockaddr * 指针,指向要绑定给sockfd的协议地址。这个地址结构根据地址创建socket时的地址协议族的不同而不同,上面给出了AF_INET的地址结构struct sockaddr_in
  • 第三个参数:addrlen 对应的是地址的长度
    返回值:
  • 成功返回0,出错返回-1
    作用:
  • 将套接字与端口号绑定,即把一个ip地址和端口号组合赋给socket

字节序转换

同一台计算机上的进程通信时不需要考虑字节序的问题,因为同一台计算机的内部架构都是一样的,处理器支持的字节序有大端字节序,还有小端字节序。大端字节序表示最大字节地址出现在最低有效字节,小端则相反。

#include <arpa/inet.h>
uint32_t htonl(uint32_t hostint32);    //返回值:以网络字节序表示的32位整数
uint32_t htons(uint16_t hostint16);    //返回值:以网络字节序表示的16位整数
uint32_t ntohl(uint32_t hostint32);    //返回值:以主机字节序表示的32位整数
uint32_t ntohs(uint16_t hostint16);    //返回值:以主机字节序表示的32位整数

连接

如果是面向连接的网络服务,在开始交换数据前,都要在请求服务的进程套接字(客户端)和提供服务的进程套接字(服务器)之间建立一个连接,使用connect函数:

#include <sys/types.h>
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

参数:

  • 第一个参数sockfd为客户端的socket描述字
  • 第二参数为服务器的socket地址
  • 第三个参数为socket地址的长度。 

返回值:

  • 成功返回0,出错返回-1

作用:

  • 客户端通过调用connect函数来建立与TCP服务器的连接

注意:在connect中所指定的地址是想与之通信的服务器地址。如果sockfd没有绑定到一个地址,connect会给调用者绑定一个默认地址!

数据传输

既然套接字端点表示文件描述符,那么只要建立连接,就可以使用write和read来通过套接字通信了。

#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
ssize_t read(int fd, void *buf, size_t count);
  • write()会把指针buf所指的内存写入count个字节到参数fd所指的文件内(文件读写位置也会随之移动),如果顺利write()会返回实际写入的字节数。当有错误发生时则返回-1,错误代码存入errno中!

  • read()会把参数fd所指的文件传送nbyte个字节到buf指针所指的内存中,成功返回读取的字节数,出错返回-1并设置errno,如果在调read之前已到达文件末尾,则这次read返回0 。

关闭套接字描述符

close函数用于关闭文件描述符

#include <unistd.h>
int close(int fd);

注意:close操作只是让相应socket描述符的引用计数-1,只有引用计数为0的时候,才会触发TCP客户端向服务器端发送终止连接请求

基于TCP的socket通信的基本流程

  1. TCP服务器端依次调用socket(),bind(),listen()之后,就会监听指定的socket地址了
  2. TCP客户端依次调用socket(),connect()之后就向TCP服务器端发送一个连接请求
  3. TCP服务器监听到这个请求后,就会调用accept()函数去接受请求,这样连接就建立好了
  4. 之后就可以开始网络IO操作了,类似普通文件的读写IO操作

基于UDP的socket通信的基本流程

UDP协议面对无连接的通信,所以UDP没有建立连接的过程!
创建一个基于udp通信协议的套接字,使用socket函数时第二个参数不能传递SOCK_STREAM,而是传递SOCK_DGRAM
比如创建一个基于IPV4地址族的UDP套接字:socket(AF_INET,SOCK_DGRAM,0);
通常用于基于UDP协议的IO一般使用recvfrom()和sendto()两个函数进行数据收发。

部分参考: http://www.cnblogs.com/Lynn-Zhang/p/5716078.html

转载于:https://www.cnblogs.com/songhexiang/p/6675526.html

学习webbench需要掌握的基础知识(webbench源代码学习心得)相关推荐

  1. DL:深度学习(神经网络)的简介、基础知识(神经元/感知机、训练策略、预测原理)、算法分类、经典案例应用之详细攻略

    DL:深度学习(神经网络)的简介.基础知识(神经元/感知机.训练策略.预测原理).算法分类.经典案例应用之详细攻略 目录 深度学习(神经网络)的简介 1.深度学习浪潮兴起的三大因素 深度学习(神经网络 ...

  2. pwn学习总结(二) —— 基础知识(持续更新)

    pwn学习总结(二) -- 基础知识(持续更新) Canary PLT表&GOT表 格式化字符串漏洞 GCC编译参数 ASLR 危险函数 输入流 syscall条件 shellcode 其它 ...

  3. JDBC 学习笔记(一)—— 基础知识 + 分页技术

    2019独角兽企业重金招聘Python工程师标准>>> 本文查阅方法:     1.查阅目录 -- 查阅本文目录,确定想要查阅的目录标题     2.快捷"查找" ...

  4. Android音视频学习系列(五) — 掌握音频基础知识并使用AudioTrack、OpenSL ES渲染PCM数据

    系列文章 Android音视频学习系列(一) - JNI从入门到精通 Android音视频学习系列(二) - 交叉编译动态库.静态库的入门 Android音视频学习系列(三) - Shell脚本入门 ...

  5. 学习插画前期需要什么基础知识?插画师入门基础先学什么?

    学习插画前期需要什么基础知识?插画师入门基础先学什么?零基础到插画师需要学多久?想必这些问题都是初学者比较伤脑筋的问题,那么初学者学习插画前期需要什么基础知识呢?今天小编就在网络上收集整理了关于插画师 ...

  6. MATLAB学习笔记2:MATLAB基础知识(下)

    阅读前请注意: 1. 该学习笔记是华中师范大学HelloWorld程序设计协会2021年寒假MATLAB培训的学习记录,是基于培训课堂内容的总结归纳.拓展阅读.博客内容由 @K2SO4钾 撰写.编辑, ...

  7. 【Python学习笔记】第一章基础知识:格式化输出,转义字符,变量类型转换,算术运算符,运算符优先级和赋值运算符,逻辑运算符,世界杯案例题目,条件判断if语句,猜拳游戏与三目运算符

    Python学习笔记之[第一章]基础知识 前言: 一.格式化输出 1.基本格式: 2.练习代码: 二.转义字符 1.基本格式: 2.练习代码: 3.输出结果: 三.输入 1.基本格式: 2.练习代码: ...

  8. 学习人工智能需要掌握哪些基础知识,需要具备哪些数学和编程技能?

    学习人工智能需要掌握以下基础知识: 数学基础:线性代数.概率论.微积分.优化等基本数学知识是人工智能领域的重要基础. 编程基础:熟悉至少一种编程语言(如Python.C++等),了解基本的数据结构和算 ...

  9. 《基础知识》提示学习的基本知识

    <基础知识>提示学习的基本知识 提示学习 背景 提示的形式和元素 提示学习的输入形式 提示学习的重要元素 提示学习的输入形式举例 基本提示任务 提示学习 内容参考:打工人转型之道(二):提 ...

  10. 学习光盘刻录必备基础知识

    学习光盘刻录必备基础知识 2011年04月11日 [b] 学习光盘刻录必备基础知识[/b] 日期:2009-10-10 11:04 1.什么是CD-R? CD-R就是光盘刻录片(CD Recordab ...

最新文章

  1. 【怎样写代码】偷窥高手 -- 反射技术(二):窥视内部
  2. R语言数据包自带数据集之ToothGrowth数据集字段解释、数据导入实战
  3. 父类中“this” 指向问题
  4. 读取list java_java 分批次读取java.util.List 数据
  5. 缺少nst linux.mbr文件,用EasyBCD2.0在Windows环境下引导Linux启动
  6. 【Excle数据透视表】如何创建非共享缓存的数据透视表
  7. SQL注入(SQL Injection)
  8. 基于Curator实现dubbo服务自动注册发现
  9. php imagecreatefromjpeg图片太大_PHP图像处理技术及应用
  10. 2016年广东省电子设计大赛健康电子专题——健康养殖远程监控系统(环境监控系统V1.0版本)
  11. python最新技术开锁工具_Python 自动化库介绍 PySimpleGUI
  12. 安装nginx之前的组件
  13. python地理空间分析——构建SimpleGIS
  14. JVM初识之类加载过程
  15. 智能中医诊疗系统php代码,智能医疗信息管理系统(中医精华版)
  16. MapGIS数据中心是什么?
  17. 苹果计算机cpu 型号怎么看,苹果电脑型号怎么看_mac电脑怎么看型号-win7之家
  18. 下一轮WiFi革命来临:详解高通MU-MIMO技术(Multi-User Multiple-Input Multiple-Output多用户多入多出技术)
  19. 钓鱼网站盯上加油卡充值
  20. android 4.0 原生短信,Android 4.0 短信发不出去解决办法

热门文章

  1. linux tcp自动重连,LabVIEW TCP/IP 断开重连问题
  2. gstreamer插件开发_测评丨高性能多媒体处理器—飞凌OKMX8MM-C开发板
  3. 单刹车信号不合理故障_航班盘旋数十圈返航 天津航空:刹车温度传感器等故障...
  4. 关于推荐系统中的特征工程
  5. python实现简单的http服务器_python实现简单http服务器功能
  6. 曼彻斯特编码_数据通信之数据编码
  7. 系统学习NLP(二)--语音合成的计算机处理综述
  8. 深度相机(六)--Kinect v2.0 手势样本库制作
  9. 7. 吴恩达机器学习课程-作业7-Kmeans and PCA
  10. 利用3D转换实现旋转木马