响应式网站报价,wordpress模板页,北京南站地图,搭建网站步骤基础知识
html#xff0c;全称为html markup language#xff0c;超文本标记语言。
http#xff0c;全称hyper text transfer protocol#xff0c;超文本传输协议。用于从万维网#xff08;WWW#xff1a;World Wide Web#xff09;服务器传输超文本到本地浏览器的传送…基础知识
html全称为html markup language超文本标记语言。
http全称hyper text transfer protocol超文本传输协议。用于从万维网WWWWorld Wide Web服务器传输超文本到本地浏览器的传送协议。
客户端请求的格式 请求方法有GET、POST等。URL请求地址。协议版本HTTP的版本。
服务器响应的格式 -----响应代号代号描述服务器上存在请求的内容并可以响应给客户端200OK客户端的请求有异常方法有问题501Method Not Implemented服务器收到请求后因为自生的问题没法响应500Internal Server Error请求的内容不存在404NOT FOUND客户端发送的请求格式有问题等(一般不存在)400BAD REQUEST http服务器实现
文件概念
文件的Inode元信息表示文件的索引节点存储着文件的元信息例如文件得创建者文件创建日期文件大小等。每个inode都有一个号码操作系统用inode号码来识别不同的文件使用命令ls -i可以查看inode号码。 stat函数
stat是C用于读取文件资源管理器的库函数头文件为
#includesys/stat.h
#includesys/types.h
#includeunisted.h
int stat(const char *path,struct stat *buf);
int fstat(int fd,struct stat *buf);
int lstat(const char *path,struct stat *buf);
parameter:path:文件路径buf:传入的保存文件状态的指针用于保存文件的状态fd:文件描述符return:成功返回0失败返回-1并设置errno
stat的结构体内容如下所示
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 */
}; 并发和并行
并发与并行的区别简单来说所谓的并发指的是多个进程按照一定的时间间隔进行只不过这个时间间隔很小人类难以感受到而已实际上在微观角度进程的并发执行还是顺序执行。
高并发高并发是互联网分布式框架设计中必须要考虑的因素之一通常指的是通过设计系统能够同时并行处理很多请求。
线程可以并行的执行任务
//头文件
#includepthread.h
//函数
int pthread_create(pthread_t *thread,const pthread_attr_t *attr,void *(*start_routine)(void *),void *arg);
pthread_t当前Linux中可理解为typedef unsigned long int pthread_t
args1:传出参数保存系统为我们分配好的线程ID
args2通常传NULL表示使用线程默认属性。若想使用具体属性也可以修改该参数。
args3函数指针指向线程主函数线程体函数运行结束则线程结束。
args4线程主函数执行期间所需要使用的函数。
在一个线程中调用pthread_create()创建新的线程后当前线程从pthread_create()返回继续往下执行而新的线程所执行的代码由我们传给pthread_create的函数指针start_routine决定。start_routine函数接收一个参数是通过pthread_create的arg参数传递给它的该参数的类型为void *这个指针按什么类型解释由调用者自己定义。start_routine的返回值类型也是void *这个指针的含义同样由调用者自己定义。start_routine返回时这个线程就退出了其它线程可以调用pthread_join得到start_routine的返回值。 pthread_create成功返回后新创建的线程的id被填写到thread参数所指向的内存单元。 attr参数表示线程属性。
pthread_exit (status) pthread_exit用于显式地退出一个线程。通常情况下pthread_exit() 函数是在线程完成工作后无需继续存在时被调用。 如果 main() 是在它所创建的线程之前结束并通过 pthread_exit() 退出那么其他线程将继续执行。否则它们将在 main() 结束时自动被终止。
gcc/g 编译时需要添加 -pthread进行编译。
gcc test.c -pthread -o test
简单的多线程实例
#include iostream
#include cstdlib
#include pthread.h
using namespace std;
#define NUM_THREADS 5
void *PrintHello(void *threadid)
{ // 对传入的参数进行强制类型转换由无类型指针变为整形数指针然后再读取int tid *((int*)threadid);cout Hello Runoob! 线程 ID, tid endl;pthread_exit(NULL);
}
int main ()
{pthread_t threads[NUM_THREADS];int indexes[NUM_THREADS];// 用数组来保存i的值int rc;int i;for( i0; i NUM_THREADS; i ){ cout main() : 创建线程, i endl;indexes[i] i; //先保存i的值// 传入的时候必须强制转换为void* 类型即无类型指针 rc pthread_create(threads[i], NULL, PrintHello, (void *)(indexes[i]));if (rc){cout Error:无法创建线程, rc endl;exit(-1);}}pthread_exit(NULL);
}
最终服务器代码
#include stdio.h
#include unistd.h
#include sys/types.h
#include sys/socket.h
#include sys/stat.h
#include ctype.h
#include arpa/inet.h
#include errno.h
#includepthread.h
#define SERVER_PORT 80
void do_http_request(int client_sock);
int get_line(int client_sock, char *buf, int size);
void do_http_response(int client_sock, const char *path);
void 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);
int main(void)
{int sock;struct sockaddr_in server_addr;sock socket(AF_INET, SOCK_STREAM, 0);// printf(wait \n);bzero(server_addr, sizeof(server_addr));server_addr.sin_family AF_INET;server_addr.sin_addr.s_addr htonl(INADDR_ANY);server_addr.sin_port htons(SERVER_PORT);bind(sock, (struct sockaddr *)server_addr, sizeof(server_addr));listen(sock, 128);printf(wait client connect\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);printf(client ip: %s \t port is : %d \n, inet_ntop(AF_INET, client.sin_addr.s_addr, client_ip, sizeof(client_ip)), ntohs(client.sin_port));pthread_t tid;int* ptr_intNULL;int err0;ptr_int(int*)malloc(sizeof(int));*ptr_intclient_sock;if(errpthread_create(tid,NULL,do_http_request,(void*)ptr_int)){printf(stderr,cannot create thread. reason: %s\n,strerror(errno));if(ptr_int) free(ptr_int);}// do_http_request(client_sock);// close(client_sock);}close(sock);return 0;
}
void* do_http_request(void* p_client_sock)
{int len 0;char buf[256], method[64], url[256], path[256];int client_sock*(int *)p_client_sock;struct stat st;// http response struct: request_method url protocol_version \r\nlen get_line(client_sock, buf, sizeof(buf));if (len 0){int i 0, j 0;while (!isspace(buf[j]) i sizeof(method) - 1){method[i] buf[j];i;j;}// set end tagmethod[i] \0;printf(method: %s\n, method);// method is GET requestif (strncasecmp(method, GET, i) 0){printf(request method is GET\n);while (isspace(buf[j])){j;}i 0;while (!isspace(buf[j]) i sizeof(url) - 1){url[i] buf[j];i;j;}url[i] \0;if (strncasecmp(url, /favicon.ico, i) 0){strcpy(url, /hello.html);}printf(url:%s\n, url);// read surplus requestdo{len get_line(client_sock, buf, sizeof(buf));printf(%s\n, buf);} while (len 0);// get local url file, and process ? in url, eg. url128.0.0.2/hel.html?wangdedefechar *pos strchr(url, ?);if (pos){// \0 represent string end tag*pos \0;printf(real url: %s\n, url);}sprintf(path, ./html_doc%s, url);printf(path:%s\n, path);// execute http response// if file is exist, to response 200, ok,and send html file,else response 404 NOT FOUNDif (stat(path, st) -1){printf(--------------------);fprintf(stderr, stat %s failed. reason :%s\n, strerror(errno));not_found(client_sock);}else{printf(*****************);if (S_ISDIR(st.st_mode)){strcat(path, /index.html);}do_http_response(client_sock, path);}}else{// request method is not GET,read http head, and response client requestfprintf(stderr, warning, other request [%s]\n, method);do{len get_line(client_sock, buf, sizeof(buf));printf(%s\n, buf);} while (len 0);// unimplement()}}else{printf(method is error);}close(client_sock);if(p_client_sock) free(p_client_sock);
}
void do_http_response(int client_sock, const char *path)
{FILE *resource NULL;resource fopen(path, r);if (resource NULL){not_found(client_sock);return;}// send http headheaders(client_sock, resource);// send http bodycat(client_sock, resource);// printf(end response!!!!);fclose(resource);
}
void headers(int client_sock, FILE *resource)
{struct stat st;int fileid 0;char temp[64];char buf[1024] {0};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);/* fstat: Get file attributes for the file, device, pipe, or socketthat file descriptor FD is open on and put them in BUF. */if (fstat(fileid, st) -1){inner_error(client_sock);}snprintf(temp, 64, Content-Length:%d\r\n\r\n, st.st_size);strcat(buf, temp);printf(stdout, header: %s, buf);if (send(client_sock, buf, strlen(buf), 0) 0){fprintf(stderr, send fail,data %s, reason %s, buf, strerror(errno));}
}
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 (len 0){fprintf(stderr, send boady error. reason %s\n, strerror(errno));break;}fprintf(stdout, %s, buf);fgets(buf, sizeof(buf), resource);}
}
int get_line(int client_sock, char *buf, int size)
{int count 0;char ch \0;int len 0;while (count size - 1 ch ! \n){len read(client_sock, ch, 1);if (len 1){if (ch \r)continue;else if (ch \n)break;buf[count] ch;count;}else if (len -1){perror(read fail);count -1;break;}else{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; 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 none xistent.\r\n\
/BODY\r\n\
/HTML;int len write(client_sock, reply, strlen(reply));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; charsetutf-8\ http-equiv\Content-Type\\r\n\
HEAD\r\n\
TITLEInner 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));fprintf(stdout, reply);if (len 0){fprintf(stderr, send reply failed. reason: %s\n, strerror(errno));}
}
最终客户端代码
#include stdio.h
#include stdlib.h
#include string.h
#include unistd.h
#include sys/socket.h
#include netinet/in.h
#define SERVER_PORT 666
#define SERVER_IP 127.0.0.1
int main(int argc, char *argv[])
{int sockfd;char *message;struct sockaddr_in servaddr;int n;char buf[64];if (argc ! 2){fputs(Usage: ./echo_client message \n, stderr);exit(1);}message argv[1];printf(message: %s\n, message);sockfd socket(AF_INET, SOCK_STREAM, 0);// 重置结构体的内存空间memset(servaddr, \0, sizeof(struct sockaddr_in));servaddr.sin_family AF_INET;inet_pton(AF_INET, SERVER_IP, servaddr.sin_addr);servaddr.sin_port htons(SERVER_PORT);connect(sockfd, (struct sockaddr *)servaddr, sizeof(servaddr));write(sockfd, message, strlen(message));n read(sockfd, buf, sizeof(buf) - 1);if (n 0){buf[n] \0;printf(receive: %s\n, buf);}else{perror(error!!!);}printf(finished.\n);close(sockfd);return 0;
}