⚠WARNING
ASP.NET에 대한 포스팅이 아닙니다
나가실 문은 오른쪽 하단입니다
나가실 문은 오른쪽 하단입니다
하기로 했던 것은 언제나 마음속 어딘가에 남아있기 마련이다.
전전편에서 언급하였던 Etag를 활용한 304를 써먹을 수 있도록 코드를 작성하였다.
public class Ftag
{
public FileInfo info = null;
public string etag = null;
public string modiTime = null;
public string minetype = null;
}
↕는 동일한 파일에 위치한다.
static readonly Dictionary<string, Ftag> fileDic = new Dictionary<string, Ftag>();
public static Ftag getFInfo(string fulPath)
{
var info = new FileInfo(fulPath);
if(info.Exists == false){
return new Ftag(){info = info};
}
var modiTime = Util.utcEng(info.LastWriteTime);
var etag = DateTime.UtcNow.Ticks.ToString("x2");
if (fileDic.GetValueOrDefault(fulPath)?.modiTime == modiTime)
{
return fileDic[fulPath];
}
var ext = Path.GetExtension(info.Name);
if(mineTypeDic.ContainsKey(ext) == false) ext = "?";
fileDic[fulPath] = new Ftag()
{
info = info,
etag = etag,
modiTime = modiTime,
minetype = mineTypeDic[ext]
};
return fileDic[fulPath];
}
Ftag클래스는 상속당해야 사용하기 편한데, FileInfo는 sealed 클래스라 상속을 허용하지 않았다.
위의 코드가 사용되는 부분
static void response(Socket client, Dictionary<string,string> dic)
{
string fpath = Util.sPath + "/public" + dic["url"];
var ftag = Util.getFInfo(fpath);
if(!ftag.info.Exists){
resForbadrequest(client, "404 Not found");
return;
}
StringBuilder sb = new StringBuilder(100);
bool m = ftag.etag == dic.GetValueOrDefault("If-None-Match");
sb.AppendLine($"HTTP/1.1 {( m ? "304 Not Modified" : "200 ok")}");
sb.AppendLine("Accept-Ranges: none");
sb.AppendLine("Cache-Control: public, max-age=0");
sb.AppendLine("Last-Modified: " + ftag.modiTime);
sb.AppendLine("Etag: " + ftag.etag);
sb.AppendLine("Date: " + Util.uTime);
sb.AppendLine("Content-type: " + ftag.minetype);
sb.AppendLine("Server: test server");
sb.AppendLine("Content-Length: " + ftag.info.Length);
sb.AppendLine("Connection: close");
sb.AppendLine();
client.Send(Encoding.UTF8.GetBytes(sb.ToString()));
if(!m) client.Send(File.ReadAllBytes(ftag.info.FullName));
}
설명: 프로그램이 최초로 실행된 이후에, 같은 내용물의 파일을 클라이언트로부터 요청받을 경우에는 304로 응답하고 파일 전송을 하지 않는다.
다음의 이미지는 이해를 돕기 위한 첫 번째, 두 번째 요청에 대한 응답 헤더의 내용이다.

설명: 두 번째는 파일을 전송하지 않으므로 1406에 해당하는 데이터 낭비를 줄일 수 있다.
Date란에 날짜의 변함이 없음을 보고 소스를 잘못 작성하였음을 깨달았다.
다음같이 수정하였다.
public static string uTime{ get {return utcEng(DateTime.Now);} }
つづく
'C# > 근웹 연대기' 카테고리의 다른 글
c#으로 근본 없는 웹서버 개발기 9 : 소켓연결버그 원인 및 해결 (0) | 2021.12.08 |
---|---|
c#으로 근본 없는 웹서버 개발기 8 : sessionID & 소켓연결버그 (0) | 2021.12.07 |
c#으로 근본 없는 웹서버 개발기 6 : minetype (0) | 2021.12.06 |
c#으로 근본 없는 웹서버 개발기 5 : 응답하라 FAVICON.ICO (0) | 2021.12.04 |
c#으로 근본 없는 웹서버 개발기 4 : HTTP 헤더정보 살피기 (0) | 2021.12.04 |