为了账号安全,请及时绑定邮箱和手机立即绑定

作业社区

探索学习新天地,共享知识资源!

0 提交作业
0 布置作业
0 满分作业
得分 100
学习任务

慕尼黑0001808 的学生作业:

// global.h #ifndef _GLOBAL_H_ #define _GLOBAL_H_ #include #include typedef struct { bool capture; //0表示不采集视频数据,1表示采集视频数据. void *start; //存放视频数据的起始地址. int length; //视频数据的长度. pthread_mutex_t update_lock; //线程锁. pthread_cond_t update_cond; //线程条件变量. } global_t; extern global_t global; #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #define LENGTH_OF(x) (sizeof(x)/sizeof(x[0])) #define PICTURE_SIZE (1024 * 1024 * 1024) //预分配图片的大小:1GB. #define BUFFER_SIZE 1024 #endif //_GLOBAL_H_ // server.h #ifndef SERVER_H #define SERVER_H #include #include #include #include // 用于 intptr_t 类型 #include #include #include #include #include #include #include #include #include "global.h" #define STD_HEADER "Connection: close\r\n" \ "Server: MJPG-Streamer/0.2\r\n" \ "Cache-Control: no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0\r\n" \ "Pragma: no-cache\r\n" \ "Expires: Mon, 3 Jan 2013 12:34:56 GMT\r\n" #define BOUNDARY "cyg-boundary" #define WEB_DIR "www" typedef enum { A_SNAPSHOT, A_STREAM, A_FILE } answer_t; //HTTP 请求 typedef struct { answer_t type; char *parm; } request_t; // TCP 服务器初始化函数 // 参数: port - 要监听的端口号 // 返回: 成功返回 socket 文件描述符,失败返回 -1 extern int init_tcp(const unsigned short port); extern void *handle_thread(void *arg); extern int analyse_http_request(const char *buf, request_t *req); extern void send_file(int sockfd, char *pathfile); #endif // SERVER_H //server.c #include "server.h" static const struct { const char *dot_extension; const char *mimetype; } mimetypes[] = { { ".html", "text/html" }, { ".htm", "text/html" }, { ".css", "text/css" }, { ".js", "text/javascript" }, { ".txt", "text/plain" }, { ".jpg", "image/jpeg" }, { ".jpeg", "image/jpeg" }, { ".png", "image/png"}, { ".gif", "image/gif" }, { ".ico", "image/x-icon" }, { ".swf", "application/x-shockwave-flash" }, { ".cab", "application/x-shockwave-flash" }, { ".jar", "application/java-archive" } }; int init_tcp(const unsigned short port) { int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { perror("socket"); return -1; } // 设置 SO_REUSEADDR 选项,允许重用地址 int opt = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) { perror("setsockopt"); close(sockfd); return -1; } int ret = 0; struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = INADDR_ANY; ret = bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)); if (ret < 0) { close(sockfd); perror("bind"); return -1; } ret = listen(sockfd, 10); if (ret < 0) { perror("listen"); close(sockfd); return -1; } return sockfd; } void *handle_thread(void *arg) { // 将指针转换回 int 值(使用 intptr_t 确保类型安全) int sockfd = (int)(intptr_t)arg; int ret = 0; char buffer[1024]; request_t request = { .type = A_SNAPSHOT, .parm = NULL, }; ret = recv(sockfd, buffer, sizeof(buffer), 0); if (ret < 0) { perror("recv"); goto end; } analyse_http_request(buffer,&request); switch(request.type) { case A_SNAPSHOT: break; case A_STREAM: break; case A_FILE: send_file(sockfd,request.parm); break; } // TODO: 在这里处理客户端连接 // 例如:读取数据、处理请求、发送响应等 end: // 关闭连接 close(sockfd); if(NULL != request.parm) { free(request.parm); request.parm = NULL; } return NULL; } int analyse_http_request(const char *buf, request_t *req) { char *url = NULL; char *url_end = NULL; url = strstr(buf,"GET /"); if (url == NULL) { return -1; } url += 5; // 跳过 "GET /" // 查找 URL 结束位置(空格、?、换行符等) url_end = url; while(*url_end && *url_end != ' ' && *url_end != '?' && *url_end != '\r' && *url_end != '\n'){ url_end++; } int len = url_end - url; if(len == 0){ // 根路径,使用默认文件 len = strlen("index.html"); req->parm = (char *)malloc(len + 1); if (req->parm == NULL) { return -1; } strcpy(req->parm, "index.html"); } else { len = MIN(len, 100); req->parm = (char *)malloc(len + 1); if (req->parm == NULL) { return -1; } memset(req->parm, 0, len + 1); memcpy(req->parm, url, len); } req->type = A_FILE; return 0; } void send_file(int sockfd, char *pathfile) { char *extension; const char *mimetype = NULL; char buffer[1024]; char filepath[1024]; if(NULL == pathfile || strlen(pathfile) == 0){ pathfile = "index.html"; } extension = strrchr(pathfile,'.'); if(NULL == extension) return; for(int i = 0; i < sizeof(mimetypes)/sizeof(mimetypes[0]); i++){ if(strcmp(extension,mimetypes[i].dot_extension) == 0){ mimetype = mimetypes[i].mimetype; break; } } if(NULL == mimetype){ return; } sprintf(filepath,"%s/%s",WEB_DIR,pathfile); printf("send_file() pathfile: %s\n",filepath); int fp = open(filepath,O_RDONLY); if(0 > fp){ perror("open() Fail to open file"); // 发送 404 错误响应 sprintf(buffer,"HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\n%s\r\n404 Not Found\r\n",STD_HEADER); send(sockfd, buffer, strlen(buffer), 0); return; } // 构建并发送 HTTP 响应头 sprintf(buffer,"HTTP/1.1 200 OK\r\nContent-Type: %s\r\n%s\r\n",mimetype,STD_HEADER); int header_len = strlen(buffer); if(send(sockfd, buffer, header_len, 0) < 0){ perror("send_file() Fail to send header"); close(fp); return; } // 读取并发送文件内容 int n; while((n = read(fp, buffer, sizeof(buffer))) > 0){ if(send(sockfd, buffer, n, 0) < 0){ perror("send_file() Fail to send file content"); break; } } close(fp); } //main.c #include #include #include "server.h" int main(int argc, char *argv[]) { int sockfd = init_tcp(8080); if (sockfd < 0) { perror("init_tcp"); return -1; } pthread_t c_tid; struct sockaddr_in c_addr; socklen_t c_addr_len = sizeof(c_addr); printf("Server started 192.168.0.191:8080\n"); printf("Hello, World!\n"); while (1) { int new_sockfd = accept(sockfd, (struct sockaddr *)&c_addr, &c_addr_len); if (new_sockfd < 0) { perror("accept"); continue; } printf("New connection accepted\n"); // 将 int 值直接转换为指针传递,避免 malloc/free // 使用 intptr_t 确保类型转换安全 if (pthread_create(&c_tid, NULL, handle_thread, (void *)(intptr_t)new_sockfd) != 0) { perror("pthread_create"); close(new_sockfd); continue; } // 分离线程,让线程结束后自动清理资源 pthread_detach(c_tid); } close(sockfd); return 0; }

微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号