[HTTP] 초 간결 한 인 스 턴 스 - HTTP 프로 토 콜 분석

네트워크 통신 의 본질은 두 컴퓨터 의 두 프로 세 스 간 의 통신 이다.예 를 들 어 브 라 우 저 프로 세 스 와 시 나 닷 컴 서버 의 한 웹 서비스 프로 세 스 가 통신 하고 있 고, QQ 프로 세 스 는 텐 센트 의 한 서버 의 한 프로 세 스 와 통신 하고 있다.
우리 가 시 나 닷 컴 을 방 문 했 을 때 무슨 일이 일 어 났 습 니까?로 컬 컴퓨터 의 프로 세 스 (브 라 우 저) 가 시 나 닷 컴 서버 에 tcp 연결 요청 을 합 니 다.이 요청 의 형식 은 무엇 입 니까?
다음은 python 이 실현 하 는 예 를 쓰 고 socket 을 만 든 다음 시 나 닷 컴 에 연결 하고 연결 한 후에 문자열 을 보 냅 니 다.코드 는 다음 과 같 습 니 다:
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(('www.sina.com.cn',80))
s.send(b'GET / HTTP/1.1\r
Host: www.sina.com.cn\r
Connection: close\r
\r
')

연결 을 만 든 후 로 컬 프로 세 스 가 시 나 닷 컴 서버 에 보 낸 메시지 의 형식 은 이 코드 입 니 다.
GET / HTTP/1.1\r
Host: www.sina.com.cn\r
Connection: close\r
\r

이 문자열 은 http 프로 토 콜 의 request 요청 입 니 다.
다음은 http 프로 토 콜 의 형식 입 니 다.
http 프로 토 콜 은 두 개의 큰 부분 으로 나 뉘 는데 하 나 는 요청 이 고 하 나 는 해당 합 니 다.요청 이 든 해당 이 든 두 부분 을 포함 합 니 다. 하 나 는 header 이 고 다른 하 나 는 body 입 니 다.(body 는 선택 가능)
HTTP GET 요청 형식:
GET /path HTTP/1.1
Header1: Value1
Header2: Value2
Header3: Value3

메모: Header 마다 한 줄 씩, 줄 바 꿈 자 는 \ r 입 니 다.
HTTP POST 요청 형식:
POST /path HTTP/1.1
Header1: Value1
Header2: Value2
Header3: Value3

body data goes here...

메모: 연속 두 개의 \ r 를 만 났 을 때 Header 부분 이 끝 났 고 뒤의 데 이 터 는 모두 Body 입 니 다.
HTTP 응답 형식:
200 OK
Header1: Value1
Header2: Value2
Header3: Value3

body data goes here...

다시 한 번 주의: HTTP 응답 이 body 를 포함 하면 \ r \ r 를 통 해 구 분 됩 니 다.
다시 한 번 주의 하 시기 바 랍 니 다. Body 의 데이터 형식 은 Content - Type 헤드 에서 확인 합 니 다. 웹 페이지 라면 Body 는 텍스트 이 고 그림 이 라면 Body 는 그림 의 바 이 너 리 데이터 입 니 다.
위의 설명 을 통 해 socket 을 이용 하여 작은 demo 를 쓰 고 http 프로 토 콜 을 이해 합 니 다.
아이디어: 로 컬 에 socket 을 만 들 고 시 나 닷 컴 서버 에 연결 한 다음 request 요청 을 위조 합 니 다.요청 은 다음 과 같 습 니 다:
GET / HTTP/1.1\r
Host: www.sina.com.cn\r
Connection: close\r
\r

image.png
다음 코드 를 실행 합 니 다:
#coding:utf-8
import socket

#  tcp socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#    
s.connect(('www.sina.com.cn',80))
s.send(b'GET / HTTP/1.1\r
Host: www.sina.com.cn\r
Connection: close\r
\r
') # buff buffer=[] while True: d=s.recv(1024) if d: buffer.append(d) else: break; # data data = b''.join(buffer) print (data) # socket s.close() # header body header, html = data.split(b'\r
\r
', 1) print(header.decode('utf-8')) # : with open('sina.html', 'wb') as f: f.write(html)

실행 결과:
 
image.png
image.png
image.png
PS: HTTP 상태 코드 상태 코드 는 세 자리 숫자 로 구성 되 어 있 습 니 다. 첫 번 째 숫자 는 응답 하 는 분 류 를 정 의 했 습 니 다. 모두 다섯 가지 유형 으로 나 뉘 어 있 습 니 다. 1xx: 지시 정보 - 요청 이 받 았 음 을 나타 내 고 2xx 를 계속 처리 합 니 다. 성공 - 요청 이 성공 적 으로 받 아들 여 졌 음 을 나타 내 고 이해 되 었 음 을 나타 냅 니 다.3xx 받 아들 이기: 리 셋 - 요청 을 완료 하려 면 더 많은 작업 을 해 야 합 니 다 4xx: 클 라 이언 트 오류 - 요청 에 문법 오류 가 있 거나 요청 이 5xx 를 실현 할 수 없습니다: 서버 쪽 오류 - 서버 가 합 법 적 인 요청 을 실현 하지 못 했 습 니 다.
PPS: 일반적인 상태 코드: 200 OK / / 클 라 이언 트 요청 성공 400 Bad Request / / 클 라 이언 트 요청 에 문법 오류 가 있 습 니 다. 서버 에 의 해 401 Unauthorized / / 요청 이 권한 이 부여 되 지 않 았 습 니 다. 이 상태 코드 는 WWW - Authenticate 헤더 필드 와 함께 403 Forbidden / / 서버 를 사용 하여 요청 을 받 아야 하지만 서비스 404 Not Found / / 요청 자원 이 존재 하지 않 습 니 다.eg: 잘못된 URL 을 입력 했 습 니 다. 500 Internal Server Error / / 서버 에 예상 치 못 한 오류 가 발생 했 습 니 다. 503 Server Unavailable / / 서버 는 현재 클 라 이언 트 의 요청 을 처리 할 수 없습니다. 일정 시간 후 정상 으로 돌아 올 수 있 습 니 다.
PPPS: 작은 예 를 추가 합 니 다. 구덩이 에 빠 진 예 를 제공 합 니 다. 동시 다발 요청 을 모 의 하 는 압력 테스트 demo 를 쓰 려 고 합 니 다. 핵심 적 인 사 고 는 다 중 프로 세 스 + 모든 프로 세 스 가 http 요청 을 보 내 는 것 입 니 다.좋 은 성능 을 내 려 면 c 로 쓰 려 고 합 니 다.
문 제 는 이 렇 습 니 다. http 요청 을 구축 할 때,
    char buf[1500];
    strcpy(request,"GET / HTTP/1.0");
    strcat(request,"\r
"); strcat(request,"User-Agent: WebBench 1.5"); strcat(request,"\r
"); strcat(request,"Host: localhost"); strcat(request,"\r
"); //bug , 。http get \r
// \r\r , , 。 // , \r
, , bug // , nginx, nginx log // log 400,400 , , bug strcat(request,"\r
"); int rlen=strlen(request);

나 는 소스 코드 를 여기에 붙 였 는데, 관심 있 는 것 은 문 제 를 다시 한 번 확인 할 수 있다.
#include "socket.c"
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define REQUEST_SIZE 2048
char request[REQUEST_SIZE];   //       HTTP  


int main(){
    char buf[1500];

    strcpy(request,"GET / HTTP/1.0");
    strcat(request,"\r
"); strcat(request,"User-Agent: WebBench 1.5"); strcat(request,"\r
"); strcat(request,"Host: localhost"); strcat(request,"\r
"); strcat(request,"\r
"); int rlen=strlen(request); printf("----test ----- the http request is ---- :
"); printf("%s",request); printf("----end ------
"); char *host="localhost"; int port=80; int s=Socket(host,port); if(s<0){ printf("error
"); return -1; } else{ printf("ok
"); } //write if(rlen!=write(s,request,rlen)){ printf("fail
"); close(s); return -1; } printf("write len is %d",rlen); //read int i=0; while(1){ i=read(s,buf,1500); printf("len i is : %d",i); if(i<0){ printf("fail
"); close(s); return -1; } if(i==0){ printf("%s",buf); printf("read comlete
"); break; } else{ printf("%s",buf); } } close(s); return 0; }

socket.c
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

int Socket(const char *host, int clientPort)
{
    int sock;
    unsigned long inaddr;
    struct sockaddr_in ad;
    struct hostent *hp;
    
    memset(&ad, 0, sizeof(ad));
    ad.sin_family = AF_INET;
    
    //        32          IPv4  
    inaddr = inet_addr(host);
    if (inaddr != INADDR_NONE)
        memcpy(&ad.sin_addr, &inaddr, sizeof(inaddr));
    else
    {
        //           ip  
        hp = gethostbyname(host);
        if (hp == NULL)
            return -1;
        memcpy(&ad.sin_addr, hp->h_addr, hp->h_length);
    }
    ad.sin_port = htons(clientPort);
    
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0)
        return sock;
    if (connect(sock, (struct sockaddr *)&ad, sizeof(ad)) < 0)
        return -1;
    return sock;
}

작성 자: zhaozhengcoder 링크:https://www.jianshu.com/p/f5a5db039737 출처: 간 서 간 서 저작권 은 작가 의 소유 이 며, 어떠한 형식의 전재 도 작가 에 게 연락 하여 권한 을 수 여 받 고 출처 를 밝 혀 주 십시오.
 
HTTP 헤드 연결 = close 역할
https://blog.csdn.net/legend_x/article/details/39578681
일부 사 이 트 는 서버 가 한 동안 실 행 된 후에 다운 되 고 이런 현상 을 초래 할 수 있 습 니 다. 예 를 들 어 tomcat 더미 와 비 더미 메모리 설정 이 부족 하고 프로그램 이 메모리 공간 을 방출 하지 못 해서 메모리 가 넘 치 거나 일부 프로 세 스 가 계속 실행 되 지 못 해서 cup 자원 이 대량으로 소모 되 었 습 니 다.
      그러나 프로그램 자체 의 원인 을 제외 하고 고객 센터 의 방문 으로 인 한 것 일 수도 있 습 니 다. (물론 이 클 라 이언 트 도 거미 소프트웨어 등 검색엔진 을 포함 합 니 다) 서버 와 클 라 이언 트 가 긴 링크 ("netstat - a" 명령 으로 네트워크 방문 정 보 를 볼 수 있 습 니 다) 를 만 들 었 다 면 http 응답 헤드 의 connection 에 대해 일정한 설정 을 해 야 합 니 다.
      소 개 는 다음 과 같다.
 
1. 설명:
 
    http 1.1 에서 request 와 reponse header 에 connection 헤더 필드 가 나타 날 수 있 습 니 다. 이 header 는 client 와 server 가 통신 할 때 긴 링크 를 어떻게 처리 하 는 지 의미 합 니 다.
    http 1.1 에서 client 와 server 는 기본적으로 상대방 이 긴 링크 를 지원 합 니 다. client 가 http 1.1 프로 토 콜 을 사용 하지만 긴 링크 를 사용 하지 않 으 려 면 header 에서 connection 의 값 을 close 로 표시 해 야 합 니 다.서버 측 도 긴 링크 를 지원 하지 않 으 려 면 response 에서 도 connection 의 값 이 close 라 는 것 을 명확 하 게 설명해 야 합 니 다.
    request 든 response 의 header 에 close 값 을 포함 하 는 connection 은 현재 사용 하고 있 는 tcp 링크 가 요청 처리 가 끝 난 후에 끊 어 진 다 는 것 을 나타 낸다.나중에 client 에서 새로운 요청 을 할 때 새로운 tcp 링크 를 만들어 야 합 니 다.HTTP Connection 의 close 설정 은 클 라 이언 트 나 서버 의 어느 한 측 이 바 텀 연결 을 닫 을 수 있 도록 합 니 다. 쌍방 은 요청 을 처리 한 후에 TCP 연결 을 닫 으 라 고 요구 합 니 다.
 
2. 프로그램 에 설정 하 는 방법:
 
    필터 에: response. setHeader ("connection", "close") 를 추가 할 수 있 습 니 다.
 
 
 
관련: 서버 해결 대량 close질문
 
 
이 문 제 를 해결 하려 면 시스템 의 인자 (/ etc / sysctl. conf 파일) 를 수정 할 수 있 습 니 다. 시스템 의 기본 시간 초과 시간 은 7200 초, 즉 2 시간 입 니 다.
기본 값 은 다음 과 같 습 니 다.
tcp_keepalive_time = 7200 seconds (2 hours) tcp_keepalive_probes = 9 tcp_keepalive_intvl = 75 seconds
 
TCP 가 idle 에 연 결 된 지 2 시간 이 지나 야 커 널 이 probe 를 시작 한 다 는 뜻 입 니 다. probe 가 9 번 (75 초 마다) 성공 하지 못 하면 커 널 은 완전히 포기 하고 이 연결 이 효력 을 잃 었 다 고 생각 합 니 다.
 
수정 후
 
sysctl -w net.ipv4.tcp_keepalive_time=30 sysctl -w net.ipv4.tcp_keepalive_probes=2 sysctl -w net.ipv4.tcp_keepalive_intvl=2
 
이 수정 을 거 친 후 서버 는 닫 히 지 않 은 tcp 연결 을 짧 은 시간 에 회수 합 니 다.
 
 

좋은 웹페이지 즐겨찾기