编写网站 支付宝,江西万通建设有限公司网站,寻甸马铃薯建设网站,网站建设一般报价多少项目需求
实现一个http 服务器项目#xff0c;服务器启动后监听80端口的tcp 连接#xff0c;当用户通过任意一款浏览器访问我们的http服务器#xff0c;http服务器会查找用户访问的html页面是否存在#xff0c;如果存在则通过http 协议响应客户端的请求#xff0c;把页面…项目需求
实现一个http 服务器项目服务器启动后监听80端口的tcp 连接当用户通过任意一款浏览器访问我们的http服务器http服务器会查找用户访问的html页面是否存在如果存在则通过http 协议响应客户端的请求把页面返回给浏览器浏览器显示html页面如果页面不存在则按照http 协议的规定通知浏览器此页面不存在404 NOT FOUND 网络协议栈中各层的功能如下 应用层根据特定的通信目的对数据进行分析处理以达到某种业务性的目的。 传输层处理传输时遇到的问题主要是保证数据传输的可靠性。 网络层完成数据的转发解决数据去哪里的问题。 链路层负责数据真正的发生过程。
数据封装与分用的过程如下 发送端在发生数据前该数据需要先自顶向下贯穿网络协议栈完成数据的封装在这个过程中每一层协议都会为该数据添加上对应的报头信息。接收端在收到数据后该数据需要先自底向上贯穿网络协议栈完成数据的解包和分用在这个过程中每一层协议都会将对应的报头信息提取出来。
需求分析
Html 页面
Html全称 Hypertext Markup Language也就是“超文本链接标示语言”。 HTML文本是由 HTML命令组成的描述性文本HTML 命令可以说明文字、 图形、动画、声音、表格、链接等。
HTTP 协议
HTTP 协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。
HTTP的特点 1.客户端服务器模式CSBS在一条通信线路上必定有一端是客户端另一端是服务器端请求从客户端发出服务器响应请求并返回。 2.简单快速客户端向服务器请求服务时只需传送请求方法和请求资源路径不需要发送额外过多的数据并且由于HTTP协议结构较为简单使得HTTP服务器的程序规模小因此通信速度很快。 3.灵活HTTP协议对数据对象没有要求允许传输任意类型的数据对象对于正在传输的数据类型HTTP协议将通过报头中的Content-Type属性加以标记。 4.无连接每次连接都只会对一个请求进行处理当服务器对客户端的请求处理完毕并收到客户端的应答后就会直接断开连接。HTTP协议采用这种方式可以大大节省传输时间提高传输效率。 5.无状态HTTP协议自身不对请求和响应之间的通信状态进行保存每个请求都是独立的这是为了让HTTP能更快地处理大量事务确保协议的可伸缩性而特意设计的。
URL格式
URLUniform Resource Lacator叫做统一资源定位符也就是我们通常所说的网址是因特网的万维网服务程序上用于指定信息位置的表示方法。
一个URL大致由如下几部分构成 1.http://表示的是协议名称表示请求时需要使用的协议通常使用的是HTTP协议或安全协议HTTPS。 2.user:pass表示的是登录认证信息包括登录用户的用户名和密码。可省略 3.www.example.jp表示的是服务器地址通常以域名的形式表示。 4.80表示的是服务器的端口号。可省略 5./dir/index.html表示的是要访问的资源所在的路径/表示的是web根目录。 6.uid1表示的是请求时通过URL传递的参数这些参数以键值对的形式通过符号分隔开。可省略 7.ch1表示的是片段标识符是对资源的部分补充。可省略 注意 如果访问服务器时没有指定要访问的资源路径那么浏览器会自动帮我们添加/但此时仍然没有指明要访问web根目录下的哪一个资源文件这时默认访问的是目标服务的首页。 大部分URL中的端口号都是省略的因为常见协议对应的端口号都是固定的比如HTTP、HTTPS和SSH对应的端口号分别是80、443和22在使用这些常见协议时不必指明协议对应的端口号浏览器会自动帮我们进行填充。
URI、URL、URN
URI、URL、URN的定义如下 URIUniform Resource Indentifier统一资源标识符用来唯一标识资源。 URLUniform Resource Locator统一资源定位符用来定位唯一的资源。 URNUniform Resource Name统一资源名称通过名字来标识资源。 URI、URL、URN三者的关系 URL是URI的一种URL不仅能唯一标识资源还定义了该如何访问或定位该资源URN也是URI的一种URN通过名字来标识资源因此URL和URN都是URI的子集。 URI有绝对和相对之分 绝对的URI对标识符出现的环境没有依赖比如URL就是一种绝对的URI同一个URL无论出现在什么地方都能唯一标识同一个资源。 相对的URI对标识符出现的环境有依赖比如HTTP请求行中的请求资源路径就是一种相对的URI这个资源路径出现在不同的主机上标识的就是不同的资源。
客户端请求
客户端发送一个HTTP请求到服务器的请求消息包括以下格式请求行request line、请求头部header、空行和请求数据四个部分组成下图给出了请求报文的一般格式 请求行[请求方法] [URI] [HTTP版本] 请求头部请求的属性这些属性都是以key: value的形式按行陈列的。 回车符换行符遇到空行表示请求报头结束。 请求数据请求正文允许为空字符串如果请求数据存在则在请求头部中会有一个Content-Length属性来标识请求正文的长度。
服务端响应
服务器响应客户端的HTTP响应也由四个部分组成分别是状态行、消息报头、空行和响应正文。 状态行[HTTP版本] [状态码] [状态码描述]。 消息报头响应的属性这些属性都是以key: value的形式按行陈列的。 回车符换行符遇到空行表示请响应报头结束。 响应正文响应正文允许为空字符串如果响应正文存在则在响应报头中会有一个Content-Length属性来标识响应正文的长度。
响应代号代号描述服务器上存在请求的内容并可以响应给客户端200OK客户端的请求有异常方法有问题501Method Not Implemented服务器收到请求后因为自身的问题没法响应500Internal Server Error请求的内容不存在404NOT FOUND客户端发送的请求格式有问题等400BAD REQUEST
HTTP常见的Header
Content-Type数据类型text/html等。 Content-Length正文的长度。 Host客户端告知服务器所请求的资源是在哪个主机的哪个端口上。 User-Agent声明用户的操作系统和浏览器的版本信息。 Referer当前页面是哪个页面跳转过来的。 Location搭配3XX状态码使用告诉客户端接下来要去哪里访问。 Cookie用户在客户端存储少量信息通常用于实现会话session的功能。
实战整了一个后台服务真香
实现 Mini 型 http 服务器 #mermaid-svg-kqPQNx5RoylsBIAz {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-kqPQNx5RoylsBIAz .error-icon{fill:#552222;}#mermaid-svg-kqPQNx5RoylsBIAz .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-kqPQNx5RoylsBIAz .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-kqPQNx5RoylsBIAz .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-kqPQNx5RoylsBIAz .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-kqPQNx5RoylsBIAz .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-kqPQNx5RoylsBIAz .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-kqPQNx5RoylsBIAz .marker{fill:#333333;stroke:#333333;}#mermaid-svg-kqPQNx5RoylsBIAz .marker.cross{stroke:#333333;}#mermaid-svg-kqPQNx5RoylsBIAz svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-kqPQNx5RoylsBIAz .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-kqPQNx5RoylsBIAz .cluster-label text{fill:#333;}#mermaid-svg-kqPQNx5RoylsBIAz .cluster-label span{color:#333;}#mermaid-svg-kqPQNx5RoylsBIAz .label text,#mermaid-svg-kqPQNx5RoylsBIAz span{fill:#333;color:#333;}#mermaid-svg-kqPQNx5RoylsBIAz .node rect,#mermaid-svg-kqPQNx5RoylsBIAz .node circle,#mermaid-svg-kqPQNx5RoylsBIAz .node ellipse,#mermaid-svg-kqPQNx5RoylsBIAz .node polygon,#mermaid-svg-kqPQNx5RoylsBIAz .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-kqPQNx5RoylsBIAz .node .label{text-align:center;}#mermaid-svg-kqPQNx5RoylsBIAz .node.clickable{cursor:pointer;}#mermaid-svg-kqPQNx5RoylsBIAz .arrowheadPath{fill:#333333;}#mermaid-svg-kqPQNx5RoylsBIAz .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-kqPQNx5RoylsBIAz .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-kqPQNx5RoylsBIAz .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-kqPQNx5RoylsBIAz .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-kqPQNx5RoylsBIAz .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-kqPQNx5RoylsBIAz .cluster text{fill:#333;}#mermaid-svg-kqPQNx5RoylsBIAz .cluster span{color:#333;}#mermaid-svg-kqPQNx5RoylsBIAz div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-kqPQNx5RoylsBIAz :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 接收http请求 解析http请求 响应http请求 在浏览器网址搜索栏输入 xxx/fei.html 登录到我的服务器端. xxx/fei.html 是我电脑的ip地址.在 linux shell 窗口 输入 ip addr 可获取本机ip
代码实现
#include iostream
#include unistd.h
#include stdio.h
#include sys/types.h
#include sys/socket.h
#include ctype.h
#include arpa/inet.h
#include string.h
#include netinet/in.h
#include errno.h
#include sys/stat.h
#include pthread.h#define SERVER_PORT 80static int debug 1;using namespace std;int get_line(int socket, char *buf, int size);
void* do_http_request(void* pclient_socket);
void do_http_response(int client_sock, const char *path);
void do_http_response1(int client_sock);int headers(int client_sock, FILE *resource);
void cat(int client_sock, FILE *resource);
void inner_error(int client_sock);
void unimplemented(int client_sock);
void bad_request(int client_sock);
void not_found(int client_sock);int main(void){int sock;//代表信箱struct sockaddr_in server_addr;//1.美女创建信箱sock socket(AF_INET, SOCK_STREAM, 0);//2.清空标签写上地址和端口号bzero(server_addr, sizeof(server_addr));server_addr.sin_family AF_INET;//选择协议族IPV4server_addr.sin_addr.s_addr htonl(INADDR_ANY);//监听本地所有IP地址server_addr.sin_port htons(SERVER_PORT);//绑定端口号//实现标签贴到收信得信箱上bind(sock, (struct sockaddr *)server_addr, sizeof(server_addr));//把信箱挂置到传达室这样就可以接收信件了listen(sock, 128);//万事俱备只等来信printf(等待客户端的连接\n);int done 1;while(done){struct sockaddr_in client;int client_sock, len, i;char client_ip[64];char buf[256];pthread_t id;int* pclient_sock NULL;socklen_t client_addr_len;client_addr_len sizeof(client);printf(come here!\n);client_sock accept(sock, (struct sockaddr *)client, client_addr_len);//打印客服端IP地址和端口号printf(client ip: %s\t port : %d\n,inet_ntop(AF_INET, client.sin_addr.s_addr,client_ip,sizeof(client_ip)),ntohs(client.sin_port));/*处理http请求读取客户端的数据*/// do_http_request(client_sock);//启动线程处理 http 请求pclient_sock (int*)malloc(sizeof(int));*pclient_sock client_sock;pthread_create(id, NULL, do_http_request, (void *)pclient_sock);// close(client_sock);}close(sock);return 0;
}void* do_http_request(void* pclient_socket){/*read client http request*/int len0;char buf[256];char method[64];char url[256];char path[512];struct stat st;int client_socket *(int*)pclient_socket;//1.read col of requestlen get_line(client_socket, buf, sizeof(buf));if(len0){ //read col of requestsint i0, j0;while(!isspace(buf[j]) (i sizeof(method)-1)){method[i] buf[j];i;j;}method[i] \0;if(debug){cout request method: method endl;}if(strncasecmp(method, GET, i) 0){ //Only handle get requestsif(debug){coutmethod GET endl;}// get urlwhile(isspace(buf[j])); //ignore spacei0;while(!isspace(buf[j]) (sizeof(url)-1)){url[i] buf[j];i;j;}url[i] \0;if(debug){couturl: urlendl;}// continue to read the header of httpdo{len get_line(client_socket, buf, sizeof(buf));if(debug){coutread: bufendl;}}while(len0);// *** Locate the local HTML address of the server***// Handle the ? in the URL{char *pos strchr(url, ?);if(pos){*pos \0;coutreal url: url endl;}}sprintf(path, ./html_docs/%s, url);if(debug){coutpath: path endl;}// Execute HTTP response// 判断文件是否存在如果存在就响应200 OK同时发送相应的html文件如果不存在就响应404 NOT FOUND.if(-1 stat(path, st)){ // if file not existfprintf(stderr, stat %s failed. reason: %s\n, path, strerror(errno));not_found(client_socket);}else{if(S_ISDIR(st.st_mode)){strcat(path, /index.html); // is directory?}//do_http_response1(client_socket);do_http_response(client_socket, path); }}else{ // no get requests, read all http headers and Response server 501 Method Not Implementedfprintf(stderr, warning! other request [%s]\n, method);do{len get_line(client_socket, buf, sizeof(buf));if(debug){coutread: bufendl;}}while(len0);unimplemented(client_socket); //}}else{ // fialed to request// bad requestbad_request(client_socket);}close(client_socket);if(pclient_socket) free(pclient_socket); //释放动态分配的内存return NULL;}void unimplemented(int client_sock){const char*reply HTTP/1.0 501 unimplemented\r\n\Content-Type: text/html\r\n\\r\n\HTML lang\zh-CN\\r\n\meta content\text/html; charsetutf-8\ http-equiv\Content-Type\\r\n\HEAD\r\n\TITLEMehod Not Implemented/TITLE\r\n\/HEAD\r\n\BODY\r\n\Punimplemented\r\n\PThe server could not fulfill your request because the resource specified is unavailable or nonexistent.\r\n\/BODY\r\n\/HTML;int len write(client_sock,reply,strlen(reply));if(debug) fprintf(stdout,reply);if(len0) fprintf(stderr,send reply failed.reason:%s\n,strerror(errno));}void bad_request(int client_sock){const char*reply HTTP/1.0 400 bad_request\r\n\Content-Type: text/html\r\n\\r\n\HTML lang\zh-CN\\r\n\meta content\text/html; charsetutf-8\ http-equiv\Content-Type\\r\n\HEAD\r\n\TITLEBad Requst/TITLE\r\n\/HEAD\r\n\BODY\r\n\PBad Request\r\n\PThe server could not fulfill your request because the resource specified is unavailable or nonexistent.\r\n\/BODY\r\n\/HTML;int len write(client_sock,reply,strlen(reply));if(debug) fprintf(stdout,reply);if(len0) fprintf(stderr,inner reply failed.reason:%s\n,strerror(errno));}void do_http_response(int client_sock, const char *path){FILE *resource NULL;int ret 0;resource fopen(path,r);if(resource NULL){not_found(client_sock);return;}// 1.send http headerret headers(client_sock, resource);// 2.send http bodyif(!ret){cat(client_sock, resource);}fclose(resource);}/*
返回关于响应文件信息的 http 头部
输入:
client_sock:客服端socket的句柄
resource:文件的句柄
返回值:success-0 fail--1
*/int headers(int client_sock, FILE *resource){struct stat st;int fileid 0;char buf[1024]{0};char tmp[64];strcpy(buf,HTTP/1.0 200 OK\r\n);strcat(buf,Server: Martin Server\r\n);strcat(buf,Content-Type: text/html\r\n);strcat(buf,Connection: Close\r\n);fileid fileno(resource);if(fstat(fileid, st) -1){inner_error(client_sock);return -1;}snprintf(tmp, 64, Content-Length: %d\r\n\r\n, st.st_size);strcat(buf,tmp);if(debug){fprintf(stdout, header: %s\n, buf);}if(send(client_sock, buf, strlen(buf), 0)0){fprintf(stderr, send failed. data: %s, reason: %s\n, buf, strerror(errno));return -1;}return 0;}// 说明:实现将html文件的内容按照行读取并发送客户端
void cat(int client_sock, FILE *resource){char buf[1024];fgets(buf, sizeof(buf), resource);while(!feof(resource)){int len write(client_sock, buf, strlen(buf));if(len0){fprintf(stderr, send body error. reason: %s\n,strerror(errno));break;}if(debug) fprintf(stdout, %s, buf);fgets(buf, sizeof(buf), resource);}}void do_http_response1(int client_sock){//响应httpconst char *main_header HTTP/1.0 200 OK\r\nServer: Martin Server\r\nContent-Type: text/html\r\nConnection: Close\r\n;const char *welcome_content \html lang\zh-CN\\n\head\n\meta content\text/html; charsetutf-8\ http-equiv\Content-Type\\n\titleThis is a test/title\n\/head\n\body\n\div aligncenter height\500px\ \n\br/br/br/\n\h2大家好/h2br/br/\n\form action\commit\ method\post\\n\尊姓大名: input type\text\ name\name\ /\n\br/芳龄几何: input type\password\ name\age\ /\n\br/br/br/input type\submit\ value\提交\ /\n\input type\reset\ value\重置\ /\n\/form\n\/div\n\/body\n\/html;//1.送main_headerint len write(client_sock, main_header, sizeof(main_header));if(debug) fprintf(stdout, ...do http response...\n);if(debug) fprintf(stdout, write[%d]:%s, len, main_header);//2.生成Content-Lengthchar send_buf[64];int wc_len strlen(welcome_content);len snprintf(send_buf,64,Content-Length: %d\r\n\r\n,wc_len);len write(client_sock,send_buf,len);if(debug) fprintf(stdout, write[%d]: %s, len, send_buf);len write(client_sock,welcome_content,wc_len);if(debug) fprintf(stdout, write[%d]: %s, len, welcome_content);}int get_line(int socket, char *buf, int size){int count 0;char ch \0;int len 0;while ((count size -1) ch ! \n){len read(socket, ch, 1);if(1 len){ // normalif(\r ch){continue;}else if(\n ch){buf[count] \0;break;}buf[count] ch;count;}else if(-1 len){ // abnormalperror(read failed);count -1;break;}else{ //read return 0: client has closed socketfprintf(stderr, client close\n);count -1;break;}}if(count0) buf[count] \0;return count; //count-1:error!! count0:read a Blank row; count 0: read a row success!}void not_found(int client_sock){const char*reply HTTP/1.0 404 NOT FOUND\r\n\Content-Type: text/html\r\n\\r\n\HTML lang\zh-CN\\r\n\meta content\text/html; charsetutf-8\ http-equiv\Content-Type\\r\n\HEAD\r\n\TITLENOT FOUND/TITLE\r\n\/HEAD\r\n\BODY\r\n\P文件不存在\r\n\PThe server could not fulfill your request because the resource specified is unavailable or nonexistent.\r\n\/BODY\r\n\/HTML;int len write(client_sock, reply, strlen(reply));if(debug) fprintf(stdout, reply);if(len0) fprintf(stderr,send reply failed.reason:%s\n,strerror(errno));
}void inner_error(int client_sock){const char*reply HTTP/1.0 500 Internal Sever Error\r\n\Content-Type: text/html\r\n\\r\n\HTML lang\zh-CN\\r\n\meta content\text/html; charsetutf-8\ http-equiv\Content-Type\\r\n\HEAD\r\n\TITLENOT FOUND/TITLE\r\n\/HEAD\r\n\BODY\r\n\P服务器内部出错\r\n\PThe server could not fulfill your request because the resource specified is unavailable or nonexistent.\r\n\/BODY\r\n\/HTML;int len write(client_sock,reply,strlen(reply));if(debug) fprintf(stdout,reply);if(len0) fprintf(stderr,inner reply failed.reason:%s\n,strerror(errno));}html 文件 览器访问服务器成功后看到的页面效果
在当前文件夹建立文件 目录 mkdir html_docs 进入这个目录 建立一个名为 fei.html 的文件将下面的 html 文本放入
html lang\zh-CN\
head
meta content\text/html; charsetutf-8 bom\ http-equiv\Content-Type\
titleThis is a test/title
/head
body
div aligncenter height\500px\
br/br/br/
h2Good guys! Welcome to China Service/h2br/br/
form actioncommit methodpost
尊姓大名: input typetext namename /
br/芳龄几何: input typepassword nameage /
br/br/br/input typesubmit value提交 /
input typereset value重置 /
/form
/div
/body
/html通过c/c在linux系统实现Mini型http服务器的并发访问
相关函数
bezro()
函数原型extern void bzero(void *s, int n) 头文件string.h 功能置字符串s的前n个字节为零且包括‘\0’ 说明无返回值
memset()
函数原型extern void *memset(void *buffer, int c, int count) 头文件string.h 功能把buffer所指内存区域的前count个字节设置成c的值。
stat 函数与 struct stat 结构体
#include sys/types.h
#include sys/stat.h
#include unistd.hint stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);作用获取文件信息 path文件的路径 buf传入的保存文件状态的指针用于保存文件的状态 返回值成功返回0失败返回-1设置errno。
struct stat
{dev_t st_dev; /* ID of device containing file */文件使用的设备号ino_t st_ino; /* inode number */ 索引节点号 mode_t st_mode; /* protection */ 文件对应的模式文件目录等nlink_t st_nlink; /* number of hard links */ 文件的硬连接数 uid_t st_uid; /* user ID of owner */ 所有者用户识别号gid_t st_gid; /* group ID of owner */ 组识别号 dev_t st_rdev; /* device ID (if special file) */ 设备文件的设备号off_t st_size; /* total size, in bytes */ 以字节为单位的文件容量 blksize_t st_blksize; /* blocksize for file system I/O */ 包含该文件的磁盘块的大小 blkcnt_t st_blocks; /* number of 512B blocks allocated */ 该文件所占的磁盘块 time_t st_atime; /* time of last access */ 最后一次访问该文件的时间 time_t st_mtime; /* time of last modification */ /最后一次修改该文件的时间 time_t st_ctime; /* time of last status change */ 最后一次改变该文件状态的时间
};S_IFMT 0170000 文件类型的位遮罩S_IFSOCK 0140000 套接字S_IFLNK 0120000 符号连接S_IFREG 0100000 一般文件S_IFBLK 0060000 区块装置S_IFDIR 0040000 目录S_IFCHR 0020000 字符装置S_IFIFO 0010000 先进先出
S_ISUID 04000 文件的(set user-id on execution)位S_ISGID 02000 文件的(set group-id on execution)位S_ISVTX 01000 文件的sticky位
S_IRUSR(S_IREAD) 00400 文件所有者具可读取权限S_IWUSR(S_IWRITE)00200 文件所有者具可写入权限S_IXUSR(S_IEXEC) 00100 文件所有者具可执行权限
S_IRGRP 00040 用户组具可读取权限S_IWGRP 00020 用户组具可写入权限S_IXGRP 00010 用户组具可执行权限
S_IROTH 00004 其他用户具可读取权限S_IWOTH 00002 其他用户具可写入权限S_IXOTH 00001 其他用户具可执行权限
上述的文件类型在POSIX中定义了检查这些类型的宏定义S_ISLNK (st_mode) 判断是否为符号连接S_ISREG (st_mode) 是否为一般文件S_ISDIR (st_mode) 是否为目录S_ISCHR (st_mode) 是否为字符装置文件S_ISBLK (s3e) 是否为先进先出S_ISSOCK (st_mode) 是否为socket若一目录具有sticky位(S_ISVTX)则表示在此目录下的文件只能被该文件所有者、此目录所有者或root来删除或改名在linux中最典型的就是这个/tmp目录啦。
st_mode 主要包含了 3 部分信息 15-12 位保存文件类型 11-9 位保存执行文件时设置的信息 8-0 位保存文件访问权限
pthread
每个线程都有一个在进程中唯一的线程标识符用一个数据类型 pthread_t 表示该数据类型在 Linux 中就是一个无符号长整型数据。
int pthread_create (pthread_t *thread,pthread_attr_t *attr,void *(*start_routine)(void *),void *arg);作用创建新的线程 返回值若创建成功返回0若出错则返回错误编号。 参数 thread 是线程标识符但这个参数不是由用户指定的而是由 pthread_create 函数在创建时将新的线程的标识符放到这个变量中。 attr 指定线程的属性可以用 NULL 表示默认属性。 start_routine 指定线程开始运行的函数。 arg 是 start_routine 所需要的参数是一个无类型指针。
结束线程 当发生以下情形之一时线程就会结束 1.线程运行的函数return了也就是线程的任务已经完成 2.线程调用了 pthread_exit 函数 3.其他线程调用 pthread_cancel 结束这个线程 4.进程调用 exec() 或 exit()结束了 5.main() 函数先结束了而且 main() 自己没有调用 pthread_exit 来等所有线程完成任务。
当然一个线程结束并不意味着它的所有信息都已经消失------僵尸线程的问题。
malloc
#includestdlib.h
//或者 #includemalloc.hextern void * malloc(unsigned int num_byte); 功能分配长度为num_byte字节的内存块 参数需要分配的内存字节数如果内存池中的可用内存可以满足这个需求malloc就返回一个指向被分配的内存块起始位置的指针 返回值如果分配成功则返回指向被分配内存的指针否则返回空指针NULL。
注意 1.malloc函数返回的是void *类型如果写成p malloc(sizeof(int));则程序无法通过编译报错“不能将void *赋值给int *类型变量”。所以必须通过int *来强制类型转换 2.函数的实参为sizeof(int)用于指明一个整形数据需要的大小如果写成 int * p (int *)malloc(1);代码也能通过编译但事实上只分配了1个字节大小的内存空间
malloc所分配的是一块连续的内存。
当内存不使用时应使用free()函数将内存块释放void free( void * pointer); 功能释放内存 参数free 函数的参数要么是NULL要么是一个先前从malloc、calloc或realloc返回的值。向free传递一个NULL参数不会产生任何效果。 返回值无
常见的动态内存错误 1.对NULL指针进行解引用操作忘记检查所请求的内存是否分配成功 2.对分配的内存进行操作时越过了分配内存的边界 3.释放并非动态分配的内存传递给free的指针必须是一个从malloc、calloc或realloc函数返回的指针 4.试图释放一块动态分配的内存的一部分释放一块内存的一部分是不允许的动态分配的内存必须整块一起释放 5.一块动态内存被释放之后被继续使用等。不要访问已经被free函数释放了的内存注意指针的复制 C语言——malloc函数详解
转义字符
转义字符转义功能ASCII 码值\0空字符0\a响铃7\b退格Backspace8\t水平制表符即横向跳格9\n换行Enter10\v竖向跳格11\f换页12\r回车13
isspace()
int isspace(int c);作用检查所传的字符是否是空白字符 返回值如果 c 是一个空白字符则该函数返回非零值true否则返回 0false
strncasecmp()
strcasecmp() 函数对字符串s1和s2执行逐字节比较忽略字符的大小写
#include strings.h
int strcasecmp(const char *s1, const char *s2);
int strncasecmp(const char *s1, const char *s2, size_t n);作用函数对字符串s1和s2执行逐字节比较忽略字符的大小写。如果发现s1分别小于、匹配或大于s2则返回一个小于、等于或大于0的整数 函数输入值 s1 / s2 对比字符串 n对比个数 函数返回值 strcasecmp()函数在忽略大小写后 如果发现s1分别小于、匹配或大于s2则返回一个小于、等于或大于零的整数。 1若参数s1和s2字符串相同则返回0 2若参数s1大于s2则返回大于0的值 3若参数s1小于s2则返回小于0的值
strcat
#include string.h
char *strcat(char *_Destination,const char *_Source)strcat函数是字符串追加函数也就是在字符串后面追加另一个字符串。
在自己实现的时候就需要提前找到被追加的字符串的尾部也就是找到\0
char* my_strcat(char* dest, const char* str)
{char* ret dest;assert(*dest ! NULL);assert(*str);//找到目的字符串里的\0while (*dest ! \0){dest;}//追加while (*dest *str){;}return ret;
}fileno()
#include stdio.h
int fileno(FILE *stream)函数说明fileno()用来取得参数stream指定的文件流所使用的文件描述词 返回值返回文件描述词
fgets()
# include stdio.h
char *fgets(char *s, int size, FILE *stream);功能是从 stream 流中读取 size 个字符存储到字符指针变量 s 所指向的内存空间。它的返回值是一个指针指向字符串中第一个字符的地址。 参数 s 代表要保存到的内存空间的首地址可以是字符数组名也可以是指向字符数组的字符指针变量名。 size 代表的是读取字符串的长度。 stream 表示从何种流中读取可以是标准输入流 stdin也可以是文件流即从某个文件中读取。
feof()
作用用于判断文件指针是否指向文件末尾 返回值当指向文件尾返回1否则返回0
在文件读取过程中不能用feof函数的返回值直接用来判断文件的是否结束 feof的正确使用场景feof应当用于在文件读取已经结束的时候判断是读取失败导致的结束还是遇到文件尾正常的结束与ferror搭配
编译文件
实现并发访问使用到线程函数 pthread_create 因此编译时要在 -o 的前面加上 pthread这个函数的库否则会报错。