【八】http服务器开发--实现一个http服务器

article/2025/9/18 18:29:21

文章目录

  • 一、整体概述
  • 二、接收http请求
  • 三、响应http请求
  • 四、完整代码即效果
    • 4.1 完整代码:
    • 4.2 实现过程
  • 附(stat函数)

一、整体概述

本节主要实现一个http服务器的示例;该http服务器的主要功能是,在浏览器端访问服务器ip+html文件名,结果为如果服务端如果存在我们想要的html文件,则将其展示在浏览器端。

整体流程下图所示:
在这里插入图片描述
主要步骤就三个,接收http请求,解析http请求,相应http请求。

二、接收http请求

这部分主要负责接收http请求,并对请求信息进行解析。

从上一节中我们知道,客户端发来的请求信息,主要包括请求行,请求头部,请求内容等组成,
在这里插入图片描述
通过解析请求行我们可以得到请求方法和URL等,然后解析请求头部信息,那怎么判断请求头部信息结束了呢?由图中可以看出,当连续解析到两个回车符时,就是请求头部结束了,剩下的就是请求数据。

首先是解析请求行,解析请求行的函数如下:

//读取请求行:返回值: -1 表示读取出错, 等于0表示读到一个空行, 大于0 表示成功读取一行
int get_line(int sock, char *buf, int size)
{int count = 0;//计数器,用来对当前已经读取的字符数进行计数char ch = '\0';//字符串结束符int len = 0;//当前读取的字符数小于传入的字符数size-1,且ch不是换行符时while( (count<size - 1) && ch!='\n'){len = read(sock, &ch, 1);//将sock里的数据读到ch中,每次读1个字符;当返回值len为1时,说明返回的是1,即读取成功if(len == 1){if(ch == '\r')//如果读到的是回车符,则continue,进行下一次循环{continue;}else if(ch == '\n')//如果读到的是换行符,说明这一行读完了,break跳出循环{//buf[count] = '\0';break;}//这里处理一般的字符buf[count] = ch;count++;}else if( len == -1 ){//读取出错perror("read failed");count = -1;break;}else {// read 返回0,客户端关闭sock 连接.fprintf(stderr, "client close.\n");count = -1;break;}}if(count >= 0) buf[count] = '\0';//为读取的这一行添加字符串结束符return count;
}

解析完请求行后,我们需要拿出请求行中的URL,然后拿到URL中包含的html文件名,并在我们本地的html文件夹中搜索是否存在该URL对应的html文件。
编写了一个名为do_http_request的函数去解析收到的请求信息,功能为解析请求拿到URL,并在本地路径中查找该html的功能,代码过程如下:

void do_http_request(int client_sock)
{int len = 0;char buf[256];char method[64];//请求的方法,是get还是postchar url[256];//请求的URLchar path[256];struct stat  st;/*读取客户端发送的http 请求*///1.读取请求行len = get_line(client_sock, buf, sizeof(buf));//请求行只要一行,因此只需要读一次即可printf("--line 96,do_http_request --,result for get_line is [%s]\n",buf);if(len > 0){   //读到了请求行,首先获取请求的方法int i=0, j=0;while(!isspace(buf[j]) && (i<sizeof(method)-1))//如果不是空格,且没超过method的容量最大值;遇到空格说明请求方法结束了{method[i] = buf[j];//用来存放请求方法,是get还是posti++;j++;}method[i] = '\0';if(debug) printf("request method: %s\n", method);if(strncasecmp(method, "GET", i)==0){ //只处理get请求if(debug) printf("method = GET\n");//获取urlwhile(isspace(buf[j++]));//跳过白空格i = 0;while(!isspace(buf[j]) && (i<sizeof(url)-1))//碰到空格则跳出循环,即读到了完整的URL{url[i] = buf[j];//用来存放URLi++;j++;}url[i] = '\0';if(debug) printf("-----url is: [%s]\n", url);//继续读取http 头部do{len = get_line(client_sock, buf, sizeof(buf));if(debug) printf("read: %s\n", buf);}while(len>0);//***定位服务器本地的html文件***//处理url 中的问号?,因为有的url是带着问号的,我们这里只取问号前面的作为URL{char *pos = strchr(url, '?');//查找问号第一次出现的位置if(pos){*pos = '\0';//将问号的地方换成\0,即字符串结束符,表示此URL到此结束printf("-----real url: [%s]\n", url);}}sprintf(path, "./html_docs/%s", url);//./html_docs是我们存放html文件的文件夹路径if(debug) printf("----path is: [%s]\n", path);//执行http 响应//判断文件是否存在,如果存在就响应200 OK,同时发送相应的html 文件,如果不存在,就响应 404 NOT FOUND.if(stat(path, &st)==-1){//文件不存在或是出错fprintf(stderr, "stat %s failed. reason: %s\n", path, strerror(errno));not_found(client_sock);}else {//文件存在if(S_ISDIR(st.st_mode)){strcat(path, "/index.html");}do_http_response(client_sock, path);}}else {//非get请求, 读取http 头部,并响应客户端 501 	Method Not Implementedfprintf(stderr, "warning! other request [%s]\n", method);do{len = get_line(client_sock, buf, sizeof(buf));if(debug) printf("read: %s\n", buf);}while(len>0);//unimplemented(client_sock);   //在响应时再实现}}else {//请求格式有问题,出错处理//bad_request(client_sock);   //在响应时再实现}}

三、响应http请求

接收并解析客户端的请求后,如果找到客户端所要求请的内容,则需要对其进行响应。

响应的格式如下所示:
主要包括响应头部(状态行+消息报头)、响应正文两部分。

在这里插入图片描述
组装响应头部的实现代码如下所示:

/*****************************返回关于响应文件信息的http 头部*输入: *     client_sock - 客服端socket 句柄*     resource    - 文件的句柄 *返回值: 成功返回0 ,失败返回-1
******************************/
int  headers(int client_sock, FILE *resource)
{struct stat st;int fileid = 0;char tmp[64];char buf[1024]={0};strcpy(buf, "HTTP/1.0 200 OK\r\n");strcat(buf, "Server: anchenliang test Server\r\n");strcat(buf, "Content-Type: text/html\r\n");strcat(buf, "Connection: Close\r\n");fileid = fileno(resource);//获取该文件的file idif(fstat(fileid, &st)== -1)//同stat函数类似,查看st文件是否存在,返回-1则说明文件不存在的{inner_error(client_sock);//发送500的错误码,表示服务器内部出错return -1;}snprintf(tmp, 64, "Content-Length: %ld\r\n\r\n", st.st_size);//连续两个回车符和换行符表示这是消息头部的结束了,st.st_size表示的是st文件的长度strcat(buf, tmp);if(debug) fprintf(stdout, "header: %s\n", buf);if(send(client_sock, buf, strlen(buf), 0) < 0)//send函数表示向socket函数发送消息,返回值小于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);//将resource文件中的内容读到buf中,fgets函数每次读取一行while(!feof(resource))//feof用来判断resource文件是否读到尾部了,文件结束返回非0,文件未结束返回0{int len = write(client_sock, buf, strlen(buf));//将buf的内容写进socket,即发送这一行内容if(len<0){//发送body 的过程中出现问题,怎么办?1.重试? 2.fprintf(stderr, "send body error. reason: %s\n", strerror(errno));break;}if(debug) fprintf(stdout, "%s", buf);fgets(buf, sizeof(buf), resource);}
}

四、完整代码即效果

实现一个http服务器,功能为输入想要访问的html文件的URL,得到正确的响应html文件。下面附上完整代码以及实现过程;

4.1 完整代码:

 #include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>#define SERVER_PORT 80static int debug = 1;int get_line(int sock, char *buf, int size);
void do_http_request(int client_sock);
void do_http_response(int client_sock, const char *path);
int  headers(int client_sock, FILE *resource);
void cat(int client_sock, FILE *resource);void not_found(int client_sock);
void inner_error(int client_sock);
void do_http_response1(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];socklen_t  client_addr_len;client_addr_len = sizeof(client);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);close(client_sock);}close(sock);return 0;
}void do_http_request(int client_sock)
{int len = 0;char buf[256];char method[64];//请求的方法,是get还是postchar url[256];//请求的URLchar path[256];struct stat  st;//用于stat函数执行后,保存文件状态/*读取客户端发送的http 请求*///1.读取请求行len = get_line(client_sock, buf, sizeof(buf));//请求行只要一行,因此只需要读一次即可printf("--line 96,do_http_request --,result for get_line is [%s]\n",buf);if(len > 0){   //读到了请求行,首先获取请求的方法int i=0, j=0;while(!isspace(buf[j]) && (i<sizeof(method)-1))//如果不是空格,且没超过method的容量最大值;遇到空格说明请求方法结束了{method[i] = buf[j];//用来存放请求方法,是get还是posti++;j++;}method[i] = '\0';if(debug) printf("request method: %s\n", method);if(strncasecmp(method, "GET", i)==0){ //只处理get请求if(debug) printf("method = GET\n");//获取urlwhile(isspace(buf[j++]));//跳过白空格i = 0;while(!isspace(buf[j]) && (i<sizeof(url)-1))//碰到空格则跳出循环,即读到了完整的URL{url[i] = buf[j];//用来存放URLi++;j++;}url[i] = '\0';if(debug) printf("-----url is: [%s]\n", url);//继续读取http 头部do{len = get_line(client_sock, buf, sizeof(buf));if(debug) printf("read: %s\n", buf);}while(len>0);//***定位服务器本地的html文件***//处理url 中的问号?,因为有的url是带着问号的,我们这里只取问号前面的作为URL{char *pos = strchr(url, '?');//查找问号第一次出现的位置if(pos){*pos = '\0';//将问号的地方换成\0,即字符串结束符,表示此URL到此结束printf("-----real url: [%s]\n", url);}}sprintf(path, "./html_docs/%s", url);//./html_docs是我们存放html文件的文件夹路径if(debug) printf("----path is: [%s]\n", path);//do_http_response1(client_sock);//执行http 响应//判断文件是否存在,如果存在就响应200 OK,同时发送相应的html 文件,如果不存在,就响应 404 NOT FOUND.if(stat(path, &st)==-1){//文件不存在或是出错fprintf(stderr, "stat %s failed. reason: %s\n", path, strerror(errno));not_found(client_sock);}else {   //文件存在if(S_ISDIR(st.st_mode))//S_ISDIR用来判断st是否是一个目录{strcat(path, "/index.html");//在path的字符串后面加上/index.html}do_http_response(client_sock, path);}}else {//非get请求, 读取http 头部,并响应客户端 501 	Method Not Implementedfprintf(stderr, "warning! other request [%s]\n", method);do{len = get_line(client_sock, buf, sizeof(buf));if(debug) printf("read: %s\n", buf);}while(len>0);//unimplemented(client_sock);   //在响应时再实现}}else {//请求格式有问题,出错处理//bad_request(client_sock);   //在响应时再实现}}/*响应http的函数*/
void do_http_response(int client_sock, const char *path)
{int ret = 0;FILE *resource = NULL;resource = fopen(path, "r");if(resource == NULL){not_found(client_sock);return ;}//1.发送http 头部ret = headers(client_sock, resource);//2.发送http body .if(!ret){cat(client_sock, resource);}fclose(resource);
}/*****************************返回关于响应文件信息的http 头部*输入: *     client_sock - 客服端socket 句柄*     resource    - 文件的句柄 *返回值: 成功返回0 ,失败返回-1
******************************/
int  headers(int client_sock, FILE *resource)
{struct stat st;int fileid = 0;char tmp[64];char buf[1024]={0};strcpy(buf, "HTTP/1.0 200 OK\r\n");strcat(buf, "Server: anchenliang test Server\r\n");strcat(buf, "Content-Type: text/html\r\n");strcat(buf, "Connection: Close\r\n");fileid = fileno(resource);//获取该文件的file idif(fstat(fileid, &st)== -1)//同stat函数类似,查看st文件是否存在,返回-1则说明文件不存在的{inner_error(client_sock);//发送500的错误码,表示服务器内部出错return -1;}snprintf(tmp, 64, "Content-Length: %ld\r\n\r\n", st.st_size);//连续两个回车符和换行符表示这是消息头部的结束了,st.st_size表示的是st文件的长度strcat(buf, tmp);if(debug) fprintf(stdout, "header: %s\n", buf);if(send(client_sock, buf, strlen(buf), 0) < 0)//send函数表示向socket函数发送消息,返回值小于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);//将resource文件中的内容读到buf中,fgets函数每次读取一行while(!feof(resource))//feof用来判断resource文件是否读到尾部了,文件结束返回非0,文件未结束返回0{int len = write(client_sock, buf, strlen(buf));//将buf的内容写进socket,即发送这一行内容if(len<0){//发送body 的过程中出现问题,怎么办?1.重试? 2.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)
{const char *main_header = "HTTP/1.0 200 OK\r\nServer: http 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; charset=utf-8\" http-equiv=\"Content-Type\">\n\
<title>This is a test</title>\n\
</head>\n\
<body>\n\
<div align=center height=\"500px\" >\n\
<br/><br/><br/>\n\
<h2>大家好,欢迎学习网络编程</h2><br/><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, strlen(main_header));if(debug) fprintf(stdout, "... do_http_response...\n");if(debug) fprintf(stdout, "write[%d]: %s", len, main_header);//2. 生成Content-Length char 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);//发送Content-Lengthif(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);}//读取请求行:返回值: -1 表示读取出错, 等于0表示读到一个空行, 大于0 表示成功读取一行
int get_line(int sock, char *buf, int size)
{int count = 0;//计数器,用来对当前已经读取的字符数进行计数char ch = '\0';//字符串结束符int len = 0;//当前读取的字符数小于传入的字符数size-1,且ch不是换行符时while( (count<size - 1) && ch!='\n'){len = read(sock, &ch, 1);//将sock里的数据读到ch中,每次读1个字符;当返回值len为1时,说明返回的是1,即读取成功if(len == 1){if(ch == '\r')//如果读到的是回车符,则continue,进行下一次循环{continue;}else if(ch == '\n')//如果读到的是换行符,说明这一行读完了,break跳出循环{//buf[count] = '\0';break;}//这里处理一般的字符buf[count] = ch;count++;}else if( len == -1 ){//读取出错perror("read failed");count = -1;break;}else {// read 返回0,客户端关闭sock 连接.fprintf(stderr, "client close.\n");count = -1;break;}}if(count >= 0) buf[count] = '\0';//为读取的这一行添加字符串结束符return count;
}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; charset=utf-8\" http-equiv=\"Content-Type\">\r\n\
<HEAD>\r\n\
<TITLE>NOT FOUND</TITLE>\r\n\
</HEAD>\r\n\
<BODY>\r\n\<P>文件不存在!\r\n\<P>The 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(len <=0){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; charset=utf-8\" http-equiv=\"Content-Type\">\r\n\
<HEAD>\r\n\
<TITLE>Inner Error</TITLE>\r\n\
</HEAD>\r\n\
<BODY>\r\n\<P>服务器内部出错.\r\n\
</BODY>\r\n\
</HTML>";int len = write(client_sock, reply, strlen(reply));if(debug) fprintf(stdout, reply);if(len <=0){fprintf(stderr, "send reply failed. reason: %s\n", strerror(errno));}
}

4.2 实现过程

第一步:将以上代码复制进minihttp.c文件中,编译:gcc minihttp.c -o minihttp
第二步:新建一个html_dock文件夹,里面放置一个test.html文件。文件内容如下所示:

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>test</title><style>body{text-align:center;padding:50px;}</style>
</head>
<body><p>恭喜,http服务器示例测试成功</p>
</body>
</html>	

第三步:运行minihttp文件,./minihttp
第四步:在浏览器访问你的ip(或者域名)+test.html,示例:http://anchenliang.com/test.html,结果如下:
在这里插入图片描述

附(stat函数)

作用:
返回文件的状态信息

头文件

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

函数原型

int 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;    /* S_ISREG(st_mode)  是一个普通文件  S_ISDIR(st_mode)  是一个目录*/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 filesystem 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 */};

http://chatgpt.dhexx.cn/article/3MtT3O0N.shtml

相关文章

蓝桥杯c语言基础试题答案,试题 基础练习 Huffuman树 蓝桥杯 C语言

资源限制 时间限制&#xff1a;1.0s 内存限制&#xff1a;512.0MB 问题描述 Huffman树在编码中有着广泛的应用。在这里&#xff0c;我们只关心Huffman树的构造过程。 给出一列数{pi}{p0, p1, …, pn-1}&#xff0c;用这列数构造Huffman树的过程如下&#xff1a; 1. 找到{pi}中最…

蓝桥杯基础试题 字母图形 C语言实现

资源限制 时间限制&#xff1a;1.0s 内存限制&#xff1a;256.0MB 问题描述 利用字母可以组成一些美丽的图形&#xff0c;下面给出了一个例子&#xff1a; ABCDEFG BABCDEF CBABCDE DCBABCD EDCBABC 这是一个5行7列的图形&#xff0c;请找出这个图形的规律&#xff0c…

蓝桥杯c语言b组试题及答案,2014蓝桥杯C语言本科B组预赛试题

2014蓝桥杯C语言本科B组预赛试题 2014 蓝桥杯 C/C语言本科 B 组预赛试题12014 蓝桥杯 C/C语言本科 B 组预赛试题(完整)1.啤酒和饮料啤酒每罐 2.3 元&#xff0c;饮料每罐 1.9 元。小明买了若干啤酒和饮料&#xff0c;一共花了 82.3 元。我们还知道他买的啤酒比饮料的数量少&am…

2018年蓝桥杯C语言B组

第一题 标题&#xff1a;第几天 2000年的1月1日&#xff0c;是那一年的第1天。 那么&#xff0c;2000年的5月4日&#xff0c;是那一年的第几天&#xff1f; 注意&#xff1a;需要提交的是一个整数&#xff0c;不要填写任何多余内容 第二题 标题&#xff1a;明码 汉字的字…

(求救大佬)蓝桥杯C语言试题 算法训练 C++ CH08 01

题目&#xff1a; 求解我的代码有什么问题&#xff0c;为什么不能通过蓝桥的编译&#xff0c;但运行结果都正确。 我的代码&#xff1a; #include<stdio.h> int main() { double ssh,zrf,y,x,g,f; int a,b,c,d,t,x1,x2,x3,x4,q; int i,j; scanf("%d%d%d%d",&a…

蓝桥杯训练题C语言

开学后就很少抽空写写题了&#xff0c;所以这次只有几道题目和大家分享一下了。 有些真题也有些VIP基础题&#xff0c;想和大家分享一下。&#xff08;有些是仿的其他博主的代码&#xff0c;&#xff0c;&#xff0c;&#xff0c;因为有些确实难&#xff08;呜呜呜~&#xff0…

蓝桥杯研究生c语言试题答案,蓝桥杯试题C语言答案.doc

蓝桥杯试题C语言答案.doc 下载提示(请认真阅读)1.请仔细阅读文档&#xff0c;确保文档完整性&#xff0c;对于不预览、不比对内容而直接下载带来的问题本站不予受理。 2.下载的文档&#xff0c;不会出现我们的网址水印。 3、该文档所得收入(下载内容预览)归上传者、原创作者&am…

蓝桥杯 C语言 试题 历届试题 格子刷油漆

试题 历届试题 格子刷油漆 问题描述   X国的一段古城墙的顶端可以看成 2*N个格子组成的矩形&#xff08;如下图所示&#xff09;&#xff0c;现需要把这些格子刷上保护漆。 你可以从任意一个格子刷起&#xff0c;刷完一格&#xff0c;可以移动到和它相邻的格子&#xff08;…

蓝桥杯 C语言 试题 历届试题 网络寻路

试题 历届试题 网络寻路 问题描述 X 国的一个网络使用若干条线路连接若干个节点。节点间的通信是双向的。某重要数据包&#xff0c;为了安全起见&#xff0c;必须恰好被转发两次到达目的地。该包可能在任意一个节点产生&#xff0c;我们需要知道该网络中一共有多少种不同的转发…

蓝桥杯 C语言 试题 算法训练 审美课

试题 算法训练 审美课 问题描述   《审美的历程》课上有n位学生&#xff0c;帅老师展示了m幅画&#xff0c;其中有些是梵高的作品&#xff0c;另外的都出自五岁小朋友之手。老师请同学们分辨哪些画的作者是梵高&#xff0c;但是老师自己并没有答案&#xff0c;因为这些画看上…

C语言课程设计——25道蓝桥杯练习题

文章目录 一、基础练习1.fib数列题目解题思路解题代码解法一(简单递推)&#xff1a;时间复杂度O(n)解法二(矩阵快速幂)&#xff1a;时间复杂度O(logn) 2.闰年判断题目解题思路解题代码 3. 数列特征题目解题思路解题代码 4.查找整数题目解题思路解题代码解法一&#xff1a;C风格…

蓝桥杯C语言程序设计真题

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、真题总结 前言 下面是蓝桥杯历年的真题希望对大家有用 一、真题 1&#xff0c;隔行变色 Excel表的格子很多&#xff0c;为了避免把某行的数据和相邻行混…

2022年第十三届蓝桥杯大赛C组真题C/C++解析(上)

**今天给大家带来2022年&#xff0c;第十三届蓝桥杯大赛的真题解析**转眼间&#xff0c;距离考试已经过去很长时间了&#xff0c;今天解元给大家解析一下&#xff0c;有问题欢迎大家指点 :笑: 下面进入正题 前言填空题1.排列字母2.特殊时间 编程题1.纸张尺寸1.1纸张大小代码 2.…

pthread+Windows环境搭建

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 为什么会要用到pthread库&#xff1f;一、pthread库下载二、使用步骤1.创建VS工程2.设置环境变量2.1动态载入2.2静态载入 三、结语 为什么会要用到pthread库&#x…

pthread_cond_timedwait函数使用

1 函数原型 #include <pthread.h>int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex,const struct timespec *restrict abstime); int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex); …

Pthread线程基础学习

后面会尝试使用冰搜和goole搜索来学习技术&#xff0c;互联网上知识的学习也是符合二八定律的&#xff0c;既然如此&#xff0c;我们何不去选择最好的文章呢。 文章参考&#xff1a; https://randu.org/tutorials/threads/ http://www.yolinux.com/TUTORIALS/LinuxTutorialPosi…

pthread 线程创建

1.1代码 #include <pthread.h> #include <stdio.h> #include <unistd.h>static int my_thread_func (void *data) {while(1){sleep(1);} }main() {pthread_t tid;int ret;// 1.创建接收线程ret pthread_create(&tid, NULL,my_thread_func, NULL);if(ret…

C语言pthread.h运用

线程概念 什么是多线程&#xff0c;提出这个问题的时候&#xff0c;我还是很老实的拿出操作系统的书&#xff0c;按着上面的话敲下“为了减少进程切换和创建开销&#xff0c;提高执行效率和节省资源&#xff0c;我们引入了线程的概念&#xff0c;与进程相比较&#xff0c;线程…

linux pthread头文件,pthread t 头文件_uint8 t 头文件_pthread t 头文件

多线程是多任务处理的一种特殊形式,多任务处理允许让电脑同时运行两个或两个以上的程序。一般情况下,两种类型的多任务处理:基于进程和基于线程。 多线程程序包含可以同时运行的两个或多个部分。这样的程序中的每个部分称为一个线程,每个线程定义了一个单独的执行路径。 本…

Day 55 Linux 线程控制语句pthread_exit pthread_join pthread_detach pthread_cancel 线程属性

目录 1. 线程控制语句 1.1pthread_exit函数 1.2pthread_join函数 1.3pthread_detach函数 1.4pthread_cancel函数 控制原语对比 2. 线程属性 2.1线程属性初始化 2.2线程的分离状态 2.3线程使用注意事项 1. 线程控制语句 1.1pthread_exit函数 将单个当前线程退出 void…