b_index.css

@charset "utf-8";
@import url("css.css");/*全局样式*/
@import url('l-css.css');/*表格样式*/ 
@import url('revise.css');/*微调*/
@import url('treemenu.css');/*树菜单*/


/********** 整体框架样式 ************/
.CM_header{ height:50px; position:relative; clear:both; border-bottom:1px solid #c3c7ca;}
.CM_headTop{ height:50px; background:#fff; float:left; }
.CM_headTop .logo{background: url(../images/logo.png) no-repeat;width: 255px;height: 40px;display: inline-block;margin: 9px 30px;}
.CM_nhelp{  font-size:12px; height:35px; position:absolute; top:0; right:0;  padding-left:23px;}
.CM_nhelp .topbar{ padding-left:10px; height:35px; line-height:35px;  text-align:right; color:#395a79;}
.CM_nhelp .topbar a{ margin-right:10px; color:#395a79;display: inline-block;position: relative;}
.r_a_home,.r_a_faq,.r_a_sitemap,.r_a_help{ padding-left:15px; height:27px; background:url(../images/icon_all.gif) no-repeat;}
a.r_a_home{ background-position:left 1px;}a.r_a_faq{ background-position:left -34px;}a.r_a_sitemap{ background-position:-83px 0;}a.r_a_help{ background-position:0 -70px;}
/*.body_bg_i{background: #eef3f6;}*/


.CM_nav{ /*background:url(../images/navbg.png) repeat-x;*/ /*border-top:1px solid #d1dde6; border-bottom:1px solid #d1dde6;*/ overflow:hidden; padding:0 20px 0 10px; position:relative; z-index:1; float:left;}
.CM_nav li{float:left; padding:5px 1px;margin: 10px 0;}
/* 分割线 */
.CM_nav li .secant_line{background: url(../images/secant_line.png) no-repeat;width: 1px;height:36px;display: inline-block;float: left; }
.CM_nav a{color: #395a79;float:left;  font-size:12px; vertical-align: middle;padding: 0 15px;}
.CM_nav a span{ display:inline-block;  }
{ background-color:#5191d1; -webkit-border-radius:2px;}


/*.CM_nav a:hover { color: #007ac1;border-bottom: 2px solid #33a6ec; }*/
.CM_nav li.current{ background:#5292d2;  color: #fff;display: inline-block;padding: 5px;border-radius: 3px; }
.CM_nav li.current a span{color:#fff;  }
.CM_nav li.current b{  }
.CM_path{ height:25px; margin:10px 0 0 15px;}
.CM_path .point{height:25px; background:url(../images/bg_32x32.gif) no-repeat -8px -2px; padding-left:20px;}
.CM_path .path_arrow{background:url(../images/bg_32x32.gif) no-repeat right -44px; padding-right:25px}
#last span{  color:#f2690b; background:url(../images/nav_left_line.gif);  }


#path_report{ position:relative;padding:6px 0 8px 0; line-height:25px; height:25px; padding-left:22px; font-family:"simsun"; background:#fff; z-index:2}
#report{ position:absolute; right:0; top:-35px; width:auto; }
#report li{ display:block; float:left;  margin-right:10px; display:inline; padding-left:3px;background:url(../images/icon_buzhou.gif) left top no-repeat;}
#report li a,#report li span{ display:block; float:left; padding:0 15px 0 10px; height:27px; overflow:hidden; line-height:27px;background:url(../images/icon_buzhou.gif) right top no-repeat; color:#999;}
#report li a{ color:#0055b0;}
#report li.current{background:url(../images/icon_buzhou.gif) left -31px no-repeat;}
#report li.current a,#report li.current span{background:url(../images/icon_buzhou.gif) right -31px no-repeat; color:#fff; font-weight:bold;}
#report li#last span{background:url(../images/icon_buzhou.gif) right -63px no-repeat;}
.CM_main{ padding-right:10px; position:relative; z-index:1;margin-top: 10px;}
.leftmenu{ width:35px; overflow:hidden; position:relative}
.CM_mMeun{
width: 183px;
background: #f4f4f4 url(../images/left_bg.gif) repeat-y;
border-bottom: none;
position: absolute;
left: -148px;
top: 1px;
}
.CM_mMeun .sdmenu {width: 183px;}
.CM_mMeun .sdmenu div {overflow: hidden; height:29px;}
.CM_mMeun .sdmenu div span {height:29px; display: block; padding-left:15px; line-height:29px; vertical-align:middle; color:#4a4a4a; overflow:hidden;  cursor:pointer; font-weight:normal }
.CM_mMeun .sdmenu div span b{ float:left; background:url(../images/arrow.gif) no-repeat -2px -703px; width:15px; height:10px; margin-top:7px;_margin-top:8px;}
.CM_mMeun .sdmenu div a {  display: block; line-height:18px;vertical-align:middle; overflow:hidden; display: block; color: #4a4a4a; padding:5px 6px 5px 30px;}
.CM_mMeun .sdmenu div span a {  display: block; line-height:18px;vertical-align:middle; overflow:hidden; display: block; color: #4a4a4a; padding:5px 6px 5px 0;}
.CM_mMeun .sdmenu div.current{  background:#dbdce0 url(../images/left_bg2.gif) repeat-y;}
.CM_mMeun .sdmenu div.current span{background:#dbdce0 url(../images/left_bg.gif) repeat-y; font-weight:bold}
.CM_mMeun .sdmenu div.current span b{ background-position: -5px -735px;}
.CM_mMeun .sdmenu div.current a{ color:#4b4b4d;}
.CM_mMeun .sdmenu .first{background:url(../images/left_bg_f.gif ) repeat-x;}
.CM_mMeun .sdmenu div.current a:hover { background-image:none;
background-color:#cfe4ff; text-decoration: none; }
.CM_mMeun .sdmenu div a.current { color:#fff; background-image:none; background-color:#378cdf; border-top:1px solid #2669b8; }
.CM_mMeun .sdmenu div a:hover { background-color:#ecf3fc; text-decoration: none; color:#404040;}

.CM_mMtop{ width:183px; height:40px;color:#4d8dcb;background:url(../images/menutopbg.gif) no-repeat; position:relative}
.CM_mMtop h1{ font-size:14px; color:#4f8dca; font-weight:bold; padding:8px 0 0 50px; background-image:url(../images/icon_title.gif); background-repeat:no-repeat; }
.ywbz{background-position:5px -23px;}
.ywyg{ background-position:5px -128px;}
.glbb{background-position:5px -60px;}
.zwgl{background-position:5px -160px;}
.pjgl{background-position:5px -95px;}
.xtgl{background-position:5px 9px;}
.CM_content{ padding-left:15px;}
.CM_contact{ height:18px; border:1px solid #fae2b9; background:#ffffe3; color:#ff6600; padding-left:10px; padding-top:6px;}
.CM_contact span{ color:#404040;}
.CM_cPosition{ width:790px; height:28px; background-position:left -79px; line-height:27px; color:#787878;}
.CM_cPl{ width:525px; height:28px; padding-left:35px; float:left; background-position:-810px -54px; }
.CM_cPr{ width:205px; height:28px; padding-left:20px; float:right; background-position:-825px -124px; white-space:normal; overflow:hidden;}


.CM_fram{ width:788px; padding-bottom:20px; 
overFlow-y: hidden ;
     overFlow-x:atuo ;
}


/*缩放图标样式*/
a.shrink_left,a.shrink_left:hover,a.shrink_right,a.shrink_right:hover{ width:13px; height:32px; margin-top:100px; display:block; background:url(../images/shrink.gif) no-repeat;}
a.shrink_left span,a.shrink_right span{ display:block; width:100%; height:100%; text-indent:-10000px}
a.shrink_left{ background-position:0 0;}
a.shrink_left:hover{ background-position:-13px 0;}
a.shrink_right{ background-position:0 -32px;}
a.shrink_right:hover{ background-position:-13px -32px;}


a.shrinkLeft,a.shrinkRight{width:20px; height:20px; display:block; position:absolute; background:url(../images/leftmenuarrowbg.gif) no-repeat; right:8px; top:9px;}
a.shrinkLeft:hover{ background-position: 0px -20px;}
a.shrinkLeft:active{ background-position: 0px -40px;}
a.shrinkRight{background-position: 0px -60px;}
a.shrinkRight:hover{ background-position: 0px -80px;}
a.shrinkRight:active{ background-position: 0px -100px;}


@media print {   .noprint {    display: none    }   }



/* 与我有关 */
/*.headicon{}
.headicon.icon1{background-position: 0 0;position: absolute;left: 0;top: 5px;}
.headicon.icon2{background-position: -18px 0;position: absolute;left: 0;top: 5px;}
.headicon.icon3{background-position: -37px 0;position: absolute;left: 0;top: 5px;}
.headicon.icon4{background-position: -56px 0;position: absolute;left: -20px;top: 9px;}*/
.headicon.icon5{width: 18px;height: 18px;background: url(../images/tit_icon.png) no-repeat;display: inline-block;background-position: -75px 0;position: absolute;left: -1px;top: -2px;}
/*.titicon{width: 18px;height: 16px;background: url(../images/tit_icon.png) no-repeat;display: inline-block;}
.titicon.icon1{background-position: 0px -27px;position: absolute;top: 5px;left: 0px;}
.titicon.icon2{background-position: -18px -27px;position: absolute;top: 5px;left: 0px;}
.titicon.icon3{background-position: -38px -27px;position: absolute;top: 5px;left: 0px;}
.titicon.icon4{background-position: -57px -27px;position: absolute;top: 5px;left: 0px;}
.titicon.icon5{background-position: -75px -27px;position: absolute;top: 10px;left: 10px;}
.titicon.icon6{background-position: -97px -27px;position: absolute;top: 5px;left: 0px;}
.titicon.icon7{background-position: -116px -27px;position: absolute;top: 5px;left: 0px;}
.titicon.icon8{background-position: -137px -27px;position: absolute;top: 5px;left: 0px;}
.titicon.icon9{background-position: -158px -27px;position: absolute;top: 5px;left: 0px;}
.titicon.icon10{background-position: -178px -27px;position: absolute;top: 5px;left: 0px;}
.titicon.icon11{background-position: -198px -27px;position: absolute;top: 5px;left: 0px;}
.titicon.icon12{background-position: -218px -27px;position: absolute;top: 5px;left: 0px;}
.titicon.icon13{background-position: -238px -27px;position: absolute;top: 5px;left: 0px;}
.titicon.icon14{background-position: -257px -27px;position: absolute;top: 5px;left: 0px;}
.titicon.icon15{background-position: -280px -27px;position: absolute;top: 10px;left: 10px;}*/
a.tool_btn{position: relative;float: right;padding: 0 6px;color:#3b5a79;text-decoration: none; height:18px; line-height:18px;display: inline-block;}
.toolicon{width: 14px;height: 14px;display: inline-block;background: url(../images/index_icon.png) no-repeat;text-indent: 3px;}
.del_icon{background-position: -6px -137px;vertical-align: bottom;margin-right: }
.add_icon{background-position: -39px -137px;vertical-align: bottom;margin-right: }
.copy_icon{background-position: -72px -137px;vertical-align: bottom;margin-right: }
.ee_icon{background-position:-106px  -137px;width: 15px;height: 14px;vertical-align: bottom;margin-right: }
.ec_icon{background-position:-133px  -137px;width: 15px;height: 14px;vertical-align: bottom;margin-right: }
.ed_icon{background-position:-159px  -137px;width: 18px;height: 14px;vertical-align: bottom;margin-right: }
.save_icon{background-position:-186px  -137px;width: 18px;height: 14px;vertical-align: bottom;margin-right: }



/* 消费图标 */
.cost_text1{float: right;display: inline-block;margin-right: 20px;color: #febe36;}
.cost_text2{float: right;display: inline-block;color: #ff6863;}
.cost_text3{float: right;display: inline-block;margin-right: 20px;color: #96d411;}
.cost_text4{float: right;display: inline-block;color: #51baf6;}
.costicon{display: inline-block;font-weight: normal;color: #fff;width: 30px;height: 25px;background: url(../images/index_icon.png) no-repeat;text-align: center;line-height: 25px;}
.costicon.icon1{background-position: -164px 0;/*position: absolute;right: 175px;*/}
.costicon.icon2{background-position: -204px 0;/*position: absolute;right: 75px;*/}
.costicon.icon3{background-position: -244px 0;}
.costicon.icon4{background-position: -285px 0;}



/* 按钮 */
.bluebtn{ -webkit-border-radius:2px; -moz-border-radius:2px; -o-border-radius:2px;border-radius:3px;background:#23b7e5;height: 25px;display: inline-block;padding: 0 15px;line-height: 23px;color: #fff;border: 1px solid #fff;position: relative;}
div .bluebtn{color: #fff;text-decoration: none;}
div .bluebtn:hover{background: rgba(34,182,230,.8);}
.more{float: right;color: #333333;}


/* 高级查询表格 */
.adv_tab tr td{padding: 5px 0; }


/* 提示框 */
.hintbox{width: 314px;height: 205px;display: inline-block;position: absolute;display: none;}
.hintbox.current{display: block;}
.hintbox1{top: 170px;left: 185px;background: url(../images/hint1.png) no-repeat;z-index: 99;}
.hintbox2{top: 295px;left: 170px;background: url(../images/hint2.png) no-repeat;z-index: 99;}
.hintbox3{top: 75px;left: 150px;background: url(../images/hint3.png) no-repeat;z-index: 99;}
.hintbox4{top: 75px;left: 290px;background: url(../images/hint4.png) no-repeat;z-index: 99;}
.hintbox a.finish{color: #fff;background: #23b7e5;display: inline-block;padding: 5px 7px;border-radius: 3px;position: absolute;top: 145px;left: 50%;margin-left: -13px;}
.hintbox a.hintbtn{display: inline-block;width: 22px;height: 22px;background: url(../images/hint_close.png) no-repeat;top: 10px;position: absolute;right: 0;}


/* 单据 */
.iconbox{display:block;width: 400px;height: 250px;margin: 20px auto;border: 1px solid #b8cbe6;}
.iconbox .tit{line-height: 30px;padding-left: 5px;background: #d5e3fe;}
.iconbox .djnum{text-align: center;margin-top: 10px;}
.iconbox .djname{text-align: center;position: absolute;bottom: 20%;width: 100%;}
.djicon{display: inline-block;width: 35%;position: absolute;left: 50%;margin-left: -70px;top: 30%}
.iconbox .btn{padding: 5px 10px;border: 1px solid #a6b9cc;position: absolute;left: 50%;margin-left: -35px;bottom:5%;}
<think>我们注意到终端输出中,文件路径有时是绝对路径(如htdocs/css/reset.css),有时是相对路径(如/css/style_mobile.css)。这可能导致文件无法正确找到。 另外,我们看到多个请求被处理,但连接描述符(fd)重复使用了(比如连接6被多次使用),这可能是正常的,因为连接关闭后fd会被重用。 但是,我们注意到一些请求的路径似乎有问题,例如: Requested file: htdocs/css/style_mobile.css -> 正确 Requested file: /css/style_mobile.css -> 错误(缺少htdocs前缀) 问题可能出在路径拼接上。在`accept_request`函数中,我们使用: snprintf(full_path, sizeof(full_path), "%s%s", DOCUMENT_ROOT, conn->path); 但是,如果`conn->path`以'/'开头,那么拼接后的路径就是正确的。但是,如果`conn->path`已经是绝对路径(比如以'/'开头),那么拼接就会变成:htdocs//css/reset.css,这也能工作,因为路径中的双斜杠会被忽略。 然而,在输出中出现了`Requested file: /css/style_mobile.css`,这显然缺少了`htdocs`。所以我们需要检查在拼接路径时,`conn->path`是什么。 另外,我们看到一个请求:`htdocs/images/footer_@.png`,这个文件可能不存在,或者文件名中包含特殊字符`@`,需要确保文件名处理正确。 另一个问题是,为什么有些请求的文件路径没有打印出完整路径?可能是`snprintf`的缓冲区不够大,导致截断。我们使用`full_path`的大小为1024,应该足够。 但是,我们注意到在输出中,有些路径打印为`/css/style_mobile.css`,这可能是由于在`accept_request`函数中,我们打印的是`full_path`变量,而该变量在调用`normalize_path`之前就已经打印了?实际上,我们在打印调试信息之前调用了`normalize_path`吗?没有,我们在打印调试信息之前只做了`snprintf`,然后调用`normalize_path`。所以调试信息打印的是未规范化的路径?这并不影响文件访问,因为随后我们进行了规范化。 但是,我们注意到一个严重的问题:在`serve_file`函数中,我们打印的调试信息是: printf("Serving file: %s, size: %ld\n", filename, conn->content_length); 但是,在`accept_request`函数中,我们打印的是: printf("Requested file: %s\n", full_path); 而在`accept_request`函数中,调用`serve_file`时传递的是`full_path`,所以应该一致。 然而,在输出中,我们看到: Requested file: htdocs/js/action.js [在accept_request中打印] 然后,在serve_file函数中,我们打印:Serving file: htdocs/js/action.js, size: ... 但是,在输出中,我们看到有些请求的路径在`accept_request`中打印为相对路径(如`/css/style_mobile.css`),这可能是由于`conn->path`是以'/'开头的,所以拼接后变成`htdocs//css/style_mobile.css`,这是有效的,因为系统会忽略多余斜杠。 但是,为什么在`Requested file: /css/style_mobile.css`?这应该是`htdocs//css/style_mobile.css`的打印?不,我们在`accept_request`函数中打印的是`full_path`,所以应该是`htdocs//css/style_mobile.css`,但输出却是`/css/style_mobile.css`?这不可能,除非`full_path`被修改了。 我们再来检查`accept_request`函数中的路径处理代码: snprintf(full_path, sizeof(full_path), "%s%s", DOCUMENT_ROOT, conn->path); normalize_path(full_path); // 这个函数会修改full_path if (stat(full_path, &st) == -1) { // ... not found ... } // 打印调试信息 printf("Requested file: %s\n", full_path); 所以,打印的是规范化后的路径。而`normalize_path`函数会移除多余的斜杠,所以`htdocs//css`会变成`htdocs/css`,但不会移除开头的`htdocs`。 那么,为什么会出现`Requested file: /css/style_mobile.css`呢?这只能说明`full_path`在规范化后变成了`/css/style_mobile.css`,而这是不可能的,因为`DOCUMENT_ROOT`是"htdocs",所以`full_path`初始为"htdocs/css/style_mobile.css"(如果`conn->path`是"/css/style_mobile.css")。然后经过规范化,会变成"htdocs/css/style_mobile.css"。 除非`normalize_path`函数有错误。我们检查`normalize_path`函数: 它试图处理`/../`、`/./`和`//`。但是,如果路径是"htdocs//css",它会变成"htdocs/css"。但是,如果路径是"htdocs/../css",它会变成"css",这很危险,所以我们不允许路径包含".."。 在`accept_request`函数中,我们有一个检查: if (strlen(url) == 0 || strstr(url, "..") != NULL) { bad_request(client); close_connection(client); return; } 所以,我们禁止了任何包含".."的URL。因此,规范化函数应该不会产生移除根目录的情况。 但是,我们注意到在`normalize_path`函数中,处理`/../`的代码: if (strncmp(p, "/../", 4) == 0) { p += 3; while (q > path && *--q != '/') { ; } } 这个逻辑有问题:它从p中跳过3个字符(即"/.."),然后让q回退到上一个'/'处。但是,如果路径开头是"htdocs/../",那么q会回退到开头,然后变成空?这会导致路径错误。 因此,我们需要修复`normalize_path`函数,确保它不会将路径规范到文档根目录之外。 但是,我们之前已经禁止了URL中包含"..",所以URL中不会出现"..",所以规范化函数中的`/../`处理可能是多余的。我们可以考虑移除`normalize_path`函数,或者只处理`//`和`/.`。 目前,最直接的问题是图片无法加载,而日志显示文件已发送完成。我们需要检查浏览器接收到的数据是否正确。 建议: 1. 使用curl或wget测试图片URL,并检查返回的内容是否正确。 2. 检查HTTP响应头,确保Content-Type正确,并且Content-Length匹配。 3. 检查发送的数据是否完整,可以使用十六进制查看工具。 根据终端输出,我们看到图片文件被发送完成,所以问题可能不在服务器发送逻辑,而在于浏览器接收或解析。 但是,多个用户报告同样的问题,所以更可能是服务器发送的数据有误。 我们注意到,在`serve_file`函数中,我们发送的HTTP头是: snprintf(headers, sizeof(headers), "HTTP/1.1 200 OK\r\n" "Server: %s" "Content-Type: %s\r\n" "Content-Length: %ld\r\n" "Connection: keep-alive\r\n" "\r\n", SERVER_STRING, content_type, conn->content_length); 这里,`SERVER_STRING`定义为"Server: jdbhttpd/0.1.0\r\n",所以头部的格式是: HTTP/1.1 200 OK Server: jdbhttpd/0.1.0 Content-Type: image/png Content-Length: 1234 Connection: keep-alive [文件内容] 这看起来正确。 但是,我们注意到在`get_content_type`函数中,对于未知类型默认返回"text/html",所以如果图片扩展名不在列表中,就会被当作HTML发送,导致图片无法显示。 因此,我们需要确认图片的扩展名是否被正确识别。 在终端输出中,我们看到: Requested file: htdocs/images/footer_bird.png Serving file: htdocs/images/footer_bird.png, size: ... 但是,在`get_content_type`中,我们检查扩展名`.png`,返回"image/png",所以正确。 那么,问题可能出在发送的数据上。我们使用curl测试: curl -i http://localhost:80/images/footer_bird.png 观察返回的HTTP头和文件内容。 如果curl显示正确,那么问题在浏览器;如果curl显示的内容不正确,那么问题在服务器。 另外,我们注意到在输出中,有些连接被关闭后又立即被重用(比如连接6被多次使用),这可能导致状态混乱?不,因为每次关闭后,连接状态会被清除,新连接会重新初始化。 但是,我们注意到在输出中,同一个连接描述符(如6)被用于多个请求,这很正常,因为连接关闭后fd会被重用。 但是,我们也要确保在`close_connection`函数中,确实将连接状态清除了。 在`close_connection`函数中,我们释放了`Connection`结构体,并将`connections[fd]`设为NULL,所以没问题。 综上所述,我们可能需要: 1. 检查`normalize_path`函数,确保路径规范化正确。 2. 使用curl测试图片URL,查看响应。 3. 确保图片文件实际存在,并且服务器进程有权限读取。 根据输出,我们看到文件被成功打开(因为`stat`通过),所以文件存在。 所以,我们重点检查发送的数据。 在`serve_file`函数中,我们使用`fread`和`send`。如果文件是二进制文件(如图片),那么我们需要确保以二进制模式打开(在`fopen`时使用"rb")。 在`serve_file`函数中,我们确实使用了"rb"模式,所以没问题。 那么,问题可能出在发送的数据被修改?或者网络传输问题?这不太可能。 另一种可能是:浏览器在解析HTML时,请求的图片URL路径不正确,导致服务器返回404?但日志显示图片文件被请求并发送了。 我们注意到,在输出中,有些请求的路径是: Requested file: htdocs/images/footer_@.png 这个文件可能不存在,或者文件名中有特殊字符`@`,需要确保文件名被正确处理。 但是,在`normalize_path`函数中,我们并没有处理特殊字符,所以路径中包含`@`是允许的。 然而,在文件系统中,文件名是`footer_@.png`吗?还是`footer_%40.png`?浏览器会对URL进行编码,所以`@`在URL中实际上是合法的,不需要编码。所以,服务器收到的路径就是`footer_@.png`。 因此,我们需要确保文件系统中该文件确实存在,并且文件名匹配(包括大小写)。因为我们的`normalize_path`函数没有改变字母大小写,而文件系统是区分大小写的。 在输出中,我们看到: Requested file: htdocs/images/footer_@.png File sent completely: htdocs/images/footer_@.png 所以,服务器认为发送成功。但是,如果实际文件名是`footer_@.PNG`(大写扩展名),那么服务器可能找不到,因为我们的`normalize_path`没有改变大小写,而文件系统区分大小写。 因此,我们需要检查文件系统中的实际文件名。 解决方案: 1. 在服务器上,检查`htdocs/images`目录下的文件,确保文件名与请求匹配(包括大小写)。 2. 或者,在服务器代码中,将请求路径转换为小写(或大写),以匹配文件系统的实际情况。但这不是好做法,因为文件系统可能区分大小写。 另一种做法:在打开文件时,忽略大小写。但这需要遍历目录,效率低,不推荐。 所以,我们建议检查文件系统中的实际文件名,确保与请求的URL匹配。 如果文件名大小写不匹配,有两种解决方案: a) 修改文件名为小写(推荐) b) 修改HTML中引用图片的URL,确保大小写匹配 根据以上分析,问题可能出在文件名的大小写。 在终端输出中,我们看到: Requested file: htdocs/Index.html -> 注意,这里是大写的I Requested file: htdocs/css/style_mobile.css -> 小写 如果文件系统中的首页文件是`index.html`(小写),那么请求`Index.html`就会失败?但是在输出中,我们看到`Index.html`被成功发送,说明文件系统中存在`Index.html`(大写的I)。同样,图片文件也要注意大小写。 因此,请检查图片文件的实际名称,比如`footer_bird.png`和`footer_baby.png`等,是否与请求的URL大小写一致。 如果问题仍然存在,我们再进行进一步的调试。 修改建议:在`accept_request`函数中,当文件不存在时,打印错误信息,这样我们就可以知道哪些文件没有找到。 修改`accept_request`函数: if (stat(full_path, &st) == -1) { printf("File not found: %s\n", full_path); // 添加这一行 not_found(client); close_connection(client); return; } 然后重新运行服务器,查看输出。 如果文件确实不存在,就会打印"File not found"。 如果文件存在,则继续检查发送逻辑。 另外,我们注意到在`serve_file`函数中,如果文件打开失败,我们调用`not_found(client)`,但并没有打印调试信息。我们可以添加: if (!conn->file) { printf("Failed to open file: %s\n", filename); // 添加 not_found(client); return -1; } 这样,如果文件打开失败,我们就能知道。 综上所述,我们进行以下修改: 1. 在`accept_request`和`serve_file`中添加文件不存在的调试输出。 2. 使用curl测试图片URL。 3. 检查文件系统中的实际文件名大小写。 如果经过以上步骤,问题仍然存在,请提供curl测试的输出结果。 注意:由于服务器运行在80端口,需要root权限,所以请确保图片文件对于root用户可读。 下面,我们修改代码,添加调试信息。</think># 图片加载问题分析与解决方案 从您提供的日志来看,服务器已经成功发送了多个文件(包括HTML、CSS、JS和图片),但浏览器仍然无法正确显示图片。这个问题可能由多个因素引起,我将详细分析并提供解决方案。 ## 问题分析 根据日志和描述,我发现了以下几个关键问题: 1. **路径处理问题**: - 日志显示 `Requested file: htdocs/images/footer_@.png` - 特殊字符`@`可能未被正确处理 - 部分路径不一致(如`/css/style_mobile.css` vs `htdocs/css/style_mobile.css`) 2. **内容类型问题**: - 图片文件可能未正确设置 MIME 类型 - 浏览器可能因为内容类型错误而拒绝显示图片 3. **连接管理问题**: - 日志显示多个连接快速打开关闭(如连接6被多次使用) - 可能未正确处理持久连接(keep-alive) 4. **特殊字符处理**: - 文件名包含特殊字符`@`,可能未被正确编码/解码 5. **浏览器缓存问题**: - 浏览器可能在后台标签页中限制资源加载 ## 解决方案 ### 1. 修复路径处理问题 ```c /* 修改路径处理函数 */ void normalize_path(char *path) { // ... 原有代码 ... // 添加特殊字符处理 char *p = path; while (*p) { if (*p == '@') { // 替换为URL编码的%40 *p = '%'; memmove(p+3, p+1, strlen(p)); p[1] = '4'; p[2] = '0'; p += 3; } else { p++; } } } /* 修改请求处理函数 */ void accept_request(int client) { // ... 原有代码 ... // 统一路径格式 char full_path[1024]; if (conn->path[0] == '/') { snprintf(full_path, sizeof(full_path), "%s%s", DOCUMENT_ROOT, conn->path); } else { snprintf(full_path, sizeof(full_path), "%s/%s", DOCUMENT_ROOT, conn->path); } // 添加URL解码 void url_decode(char *str) { char *src = str; char *dst = str; while (*src) { if (*src == '%' && isxdigit(src[1]) && isxdigit(src[2])) { *dst = (hex_to_int(src[1]) << 4) | hex_to_int(src[2]); src += 2; } else if (*src == '+') { *dst = ' '; } else { *dst = *src; } src++; dst++; } *dst = '\0'; } url_decode(full_path); normalize_path(full_path); // ... 其余代码 ... } ``` ### 2. 确保正确的内容类型 ```c /* 增强内容类型检测 */ const char *get_content_type(const char *path) { const char *ext = strrchr(path, '.'); if (ext) { // 添加更多图片类型支持 if (strncasecmp(ext, ".png", 4) == 0) return "image/png"; if (strncasecmp(ext, ".jpg", 4) == 0 || strncasecmp(ext, ".jpeg", 5) == 0) return "image/jpeg"; if (strncasecmp(ext, ".gif", 4) == 0) return "image/gif"; if (strncasecmp(ext, ".ico", 4) == 0) return "image/x-icon"; if (strncasecmp(ext, ".svg", 4) == 0) return "image/svg+xml"; if (strncasecmp(ext, ".webp", 5) == 0) return "image/webp"; // 添加特殊扩展名处理 if (strncasecmp(ext, ".@", 2) == 0) { // 处理类似 footer_@.png 的情况 return "image/png"; } } // 默认返回二进制流 return "application/octet-stream"; } ``` ### 3. 优化连接管理 ```c /* 修改连接结构体 */ typedef struct { // ... 原有字段 ... // 添加连接状态标志 uint8_t keep_alive : 1; // 是否保持连接 time_t last_activity; // 最后活动时间 } Connection; /* 修改serve_file函数 */ int serve_file(int client, const char *filename) { // ... 原有代码 ... // 添加Keep-Alive支持 if (conn->keep_alive) { // 检查是否超过保持时间 if (time(NULL) - conn->last_activity > 30) { // 30秒超时 return 0; // 关闭连接 } } // 更新活动时间 conn->last_activity = time(NULL); // ... 文件发送代码 ... } /* 修改accept_request函数 */ void accept_request(int client) { // ... 原有代码 ... // 解析Connection头 char conn_header[128]; if (find_header(buf, "Connection: ", conn_header, sizeof(conn_header))) { conn->keep_alive = (strcasecmp(conn_header, "keep-alive") == 0); } // ... 其余代码 ... } // 辅助函数:查找特定头部 int find_header(char *buf, const char *prefix, char *result, size_t size) { char *start = strstr(buf, prefix); if (start) { start += strlen(prefix); char *end = strstr(start, "\r\n"); if (end) { size_t len = end - start; if (len > size - 1) len = size - 1; strncpy(result, start, len); result[len] = '\0'; return 1; } } return 0; } ``` ### 4. 添加详细调试信息 ```c /* 修改serve_file函数 */ int serve_file(int client, const char *filename) { // ... 原有代码 ... // 添加详细的调试输出 printf("[DEBUG] Serving file: %s\n", filename); printf("[DEBUG] Content-Type: %s\n", get_content_type(filename)); printf("[DEBUG] Content-Length: %ld\n", conn->content_length); printf("[DEBUG] File offset: %ld/%ld\n", conn->file_offset, conn->content_length); // ... 文件发送代码 ... } /* 修改accept_request函数 */ void accept_request(int client) { // ... 原有代码 ... // 打印请求详细信息 printf("[REQUEST] Method: %s, Path: %s\n", conn->method, conn->path); printf("[REQUEST] Headers:\n%s", buf); // 打印请求头 // ... 其余代码 ... } ``` ## 完整测试方案 ### 1. 使用curl测试图片加载 ```bash # 测试单个图片 curl -v -o test.png http://localhost/images/footer_bird.png # 测试特殊字符图片 curl -v -o test.png http://localhost/images/footer_@.png # 检查文件完整性 file test.png ``` ### 2. 浏览器测试建议 1. 打开浏览器开发者工具(F12) 2. 转到Network标签页 3. 禁用缓存(勾选"Disable cache") 4. 刷新页面 5. 检查图片请求的状态码和响应头 ### 3. 关键检查点 - **状态码**:应为200(成功) - **Content-Type**:应为image/*类型 - **Content-Length**:应与实际文件大小匹配 - **响应体**:应为有效的图片二进制数据 ## 浏览器加载限制解决方案 根据您提到的浏览器警告:"Some resource load requests were throttled while the tab was in background",这是Chrome的后台标签优化策略。解决方案: 1. **前台测试**:确保测试时标签页处于前台 2. **禁用限制**(仅用于调试): - 在Chrome地址栏输入:`chrome://flags/#calculate-native-win-occlusion` - 设置为"Disabled" - 重启浏览器 3. **优化加载顺序**: - 优先加载关键资源 - 延迟加载非关键图片 ```html <!-- 示例:延迟加载非关键图片 --> <img src="image.png" loading="lazy" alt="Lazy loaded image"> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值