WebSocket 서버는 여러 수신 연결 요청을 어떻게 처리합니까?
여기 에 따르면 :
HTTP 업그레이드 헤더는 서버 가 애플리케이션 계층 프로토콜을 HTTP에서 WebSocket 프로토콜로 전환하도록 요청 합니다 .
클라이언트 핸드 셰이크는 IE10과 서버간에 HTTP-on-TCP 연결을 설정했습니다. 서버가 101 응답을 반환 한 후 애플리케이션 계층 프로토콜은 HTTP에서 이전에 설정된 TCP 연결을 사용하는 WebSocket으로 전환합니다.
HTTP는 이 시점에서 완전히 불가능 합니다. 이제 경량 WebSocket 유선 프로토콜을 사용하여 메시지를 언제든지 두 끝점에서 보내거나받을 수 있습니다.
따라서 내 이해는 첫 번째 클라이언트가 서버와의 핸드 셰이크를 마친 후 서버의 80 포트가 WebSocket 프로토콜에 의해 독점 된다는 것 입니다. 그리고 HTTP는 더 이상 80 포트에서 작동하지 않습니다 .
두 번째 클라이언트는 어떻게 서버와 핸드 셰이크를 교환 할 수 있습니까? 결국 WebSocket 핸드 셰이크는 HTTP 형식입니다.
1 추가
지금까지 모든 답변에 감사드립니다. 정말 도움이됩니다.
이제 동일한 서버의 80 포트가 여러 연결에서 공유 된다는 것을 이해 TCP
합니다. 그리고이 공유는 완전히 괜찮습니다. 왜냐하면 TCP
연결은 5 요소 튜플에 의해 식별 되기 때문 Jan-Philip Gehrcke
입니다.
몇 가지 생각을 추가하고 싶습니다.
WebSocket
및 둘 다 HTTP
단지 응용 프로그램 수준 프로토콜입니다. 일반적 으로 둘 다 TCP
전송으로 프로토콜에 의존합니다 .
포트 80을 선택하는 이유는 무엇입니까?
WebSocket 디자인 은 핸드 셰이크 및 후속 통신을 위해 의도적으로 서버의 포트 80을 선택합니다 . 나는 디자이너가 WebSocket 통신을 전송 수준의 관점에서 정상적인 HTTP 통신 처럼 보이게 만들고 싶어한다고 생각합니다 (즉, 서버 포트 번호는 여전히 80입니다) . 그러나 jfriend00
의 답변에 따르면이 트릭이 항상 네트워크 인프라를 속이는 것은 아닙니다.
프로토콜이 HTTP 에서 WebSocket으로 어떻게 이동합니까?
RFC 6455-WebSocket 프로토콜
기본적으로 웹의 제약 조건을 감안할 때 가능한 한 원시 TCP를 스크립트에 노출하는 것과 비슷합니다. 또한 핸드 셰이크가 유효한 HTTP 업그레이드 요청이되도록하여 서버가 HTTP 서버와 포트를 공유 할 수 있도록 설계되었습니다. 개념적으로 다른 프로토콜을 사용하여 클라이언트-서버 메시징을 설정할 수 있지만 WebSockets의 목적은 HTTP 및 배포 된 HTTP 인프라 (예 : 프록시)와 공존 할 수있는 비교적 간단한 프로토콜을 제공하는 것입니다. 사용을 단순화하고 간단한 일 (예 : 메시지 의미 체계 추가)을 유지하기위한 대상 추가와 함께 보안 고려 사항이 주어진 이러한 인프라와 함께 사용합니다.
그래서 나는 다음 진술에서 내가 틀렸다고 생각합니다.
핸드 셰이크 요청 은 HTTP 요청을 모방 하지만 뒤 따르는 통신은 그렇지 않습니다. 핸드 셰이크 요청은 포트 80의 서버에 도착합니다. 80 포트이므로 서버는이를 HTTP 프로토콜로 처리합니다. 이것이 바로 WebSocket 핸드 셰이크 요청이 HTTP 형식이어야하는 이유입니다. 그렇다면 WebSocket 관련 사항을 인식하도록 HTTP 프로토콜을 수정 / 확장 해야 한다고 생각합니다 . 그렇지 않으면 WebSocket 프로토콜에 양보 해야한다는 사실을 깨닫지 못합니다 .
다음과 같이 이해되어야한다고 생각합니다.
WebSocket 통신은 클라이언트에서 서버 로의 유효한 HTTP 요청으로 시작됩니다 . 따라서 HTTP 프로토콜을 따라 핸드 셰이크 요청을 구문 분석하고 프로토콜 변경 요청을 식별 하는 것은 서버입니다 . 그리고 프로토콜을 전환하는 서버입니다. 따라서 HTTP 프로토콜은 변경할 필요가 없습니다. HTTP 프로토콜은 WebSocket에 대해 알 필요도 없습니다.
WebSocket과 Comet
따라서 WebSocket은 양방향 통신 문제를 해결하기 위해 WebSoket이 현재 HTTP 영역 내에서 자신을 제한하지 않는다는 점 에서 Comet 기술과 다릅니다 .
2 추가
관련 질문 : 브라우저는 80 포트에서 웹 서버와 어떻게 연결합니까? 세부?
다른 답변은 이미 도움이되었습니다. 나는 귀하의 질문에 아주 좋은 하나라고 지적하고, 관련된 관점에서 대답 할 싶어 listen()
하고 accept()
. 이 두 시스템 호출의 동작은 질문에 대답하기에 충분해야합니다.
TCP / IP의 작동 방식에 관심이 있습니다!
질문의 핵심 부분에 대해서는 HTTP 또는 WebSocket에 따라 실제로 차이가 없습니다. 공통점은 IP를 통한 TCP이며 질문에 대답하기에 충분합니다. 그래도 WebSocket이 TCP와 어떻게 관련되는지에 대한 답변을받을 자격이 있습니다 ( 여기 에서 조금 더 자세히 설명하려고했습니다 ). HTTP 요청을 보내려면 두 당사자간에 설정된 TCP / IP 연결이 필요합니다. 간단한 웹 브라우저 / 웹 서버 시나리오의 경우
- 첫째, 둘 사이에 TCP 연결이 설정됩니다 (클라이언트에 의해 시작됨).
- 그런 다음 해당 TCP 연결을 통해 HTTP 요청이 전송됩니다 (클라이언트에서 서버로).
- 그런 다음 HTTP 응답이 동일한 TCP 연결을 통해 전송됩니다 (다른 방향으로 서버에서 클라이언트로).
이 교환 후에는 기본 TCP 연결이 더 이상 필요하지 않으며 일반적으로 파괴 / 연결 해제됩니다. HTTP 업그레이드 요청의 경우 기본 TCP 연결이 계속 유지되고 WebSocket 통신은 처음에 생성 된 것과 동일한 TCP 연결을 통과합니다 (위의 단계 (1)).
보시다시피 WebSocket과 표준 HTTP의 유일한 차이점은 기본 전송 채널 (TCP / IP 연결)을 변경하지 않고 높은 수준의 프로토콜 (HTTP에서 WebSocket으로)의 전환입니다.
동일한 소켓을 통해 여러 IP 연결 시도를 처리하는 방법은 무엇입니까?
이것은 내가 한때 나 자신과 어려움을 겪었고 많은 사람들이 이해하지 못하는 주제입니다. 그러나 운영 체제에서 제공하는 기본 소켓 관련 시스템 호출이 작동하는 방식을 이해하면 개념은 실제로 매우 간단합니다.
먼저, IP 연결은 다음과 같은 5 가지 정보로 고유하게 정의 된다는 점을 인식해야합니다 .
IP : 시스템 A의 포트 와 IP : 기계 B의 포트 와 프로토콜 (TCP 또는 UDP)
이제 소켓 객체는 종종 연결을 나타내는 것으로 생각됩니다. 그러나 그것은 전적으로 사실이 아닙니다. 그들은 다른 것을 나타낼 수 있습니다 : 그들은 능동적이거나 수동적 일 수 있습니다. 수동 / 수신 모드 의 소켓 객체는 매우 특별한 작업을 수행하며 질문에 대답하는 데 중요합니다. http://linux.die.net/man/2/listen 말한다 :
listen ()은 sockfd가 참조하는 소켓을 수동 소켓, 즉 accept (2)를 사용하여 들어오는 연결 요청을 수락하는 데 사용되는 소켓으로 표시합니다.
따라서 들어오는 연결 요청을 수신 하는 수동 소켓을 만들 수 있습니다 . 정의에 따라 이러한 소켓은 연결을 나타낼 수 없습니다. 연결 요청 만 수신합니다.
에 이상하자 머리 accept()
( http://linux.die.net/man/2/accept ) :
accept () 시스템 호출은 연결 기반 소켓 유형 (SOCK_STREAM, SOCK_SEQPACKET)과 함께 사용됩니다. 청취 소켓 sockfd에 대해 보류중인 연결 큐에서 첫 번째 연결 요청을 추출하고 새 연결된 소켓을 만들고 해당 소켓을 참조하는 새 파일 설명자를 반환합니다. 새로 생성 된 소켓이 수신 대기 상태가 아닙니다. 원래 소켓 sockfd는이 호출의 영향을받지 않습니다.
귀하의 질문에 답하기 위해 우리가 알아야 할 전부입니다. 이전에 생성 된 패시브 소켓 accept()
의 상태를 변경하지 않습니다 . 활성화 된 (연결된) 소켓을 반환합니다 ( 그러면 소켓은 위의 5 가지 정보 상태를 나타냅니다. 간단 하죠?). 일반적으로 새로 생성 된이 활성 소켓 개체는 다른 프로세스 나 스레드 또는 연결을 처리하는 "엔티티"로 전달됩니다. 이 연결된 소켓 객체를 반환 한 후 패시브 소켓에서 다시 호출 할 수 있으며 ,이를 수락 루프 라고 합니다 . 하지만 전화accept()
accept()
accept()
시간이 걸리죠? 들어오는 연결 요청을 놓칠 수 없습니까? 방금 인용 한 도움말 텍스트에 더 많은 필수 정보가 있습니다. 보류중인 연결 요청 대기열이 있습니다! 운영 체제의 TCP / IP 스택에 의해 자동으로 처리됩니다. 즉 accept()
, 들어오는 연결 요청을 하나씩 만 처리 할 수 있지만 높은 속도로 또는 (준) 동시에 들어오는 경우에도 들어오는 요청을 놓칠 수 없습니다. 의 동작은 accept()
시스템이 처리 할 수있는 수신 연결 요청의 빈도를 제한하는 것이라고 말할 수 있습니다. 그러나 이것은 빠른 시스템 호출이며 실제로는 다른 제한 사항이 우선 적용됩니다. 일반적으로 지금까지 수락 된 모든 연결을 처리하는 것과 관련된 제한 사항 입니다.
여기에서 빠진 것처럼 보이는 비교적 간단한 것은 서버 (특히 HTTP 서버에 대한)에 대한 각 연결 이 자체 소켓을 생성 한 다음 해당 소켓에서 실행된다는 것입니다. 한 소켓에서 발생하는 일은 현재 연결된 다른 소켓에서 발생하는 것과 완전히 독립적 입니다. 따라서 한 소켓이 webSocket 프로토콜로 전환 될 때 다른 현재 또는 들어오는 소켓 연결에 발생하는 상황은 변경되지 않습니다. 그들은 처리 방법을 스스로 결정할 수 있습니다.
따라서 오픈 소켓은 webSocket 프로토콜을 사용하는 반면 다른 수신 연결은 일반 HTTP 요청 또는 새 webSocket 연결 생성 요청 일 수 있습니다.
따라서 다음과 같은 유형의 시퀀스를 가질 수 있습니다.
- 클라이언트 A는 HTTP 요청으로 포트 80의 서버에 연결하여 webSocket 연결을 시작합니다. 이 프로세스는 둘 사이에 소켓을 만듭니다.
- 서버는 webSocket 업그레이드 요청에 yes로 응답하고 클라이언트와 서버 모두이 소켓 의 프로토콜 을 webSocket 프로토콜 로만 전환합니다.
- 클라이언트 A와 서버는 webSocket 프로토콜을 사용하여 패킷 교환을 시작하고 다음 몇 시간 동안 계속합니다.
- 클라이언트 B는 일반 HTTP 요청을 사용하여 포트 80에서 동일한 서버에 연결합니다. 이 프로세스는 둘 사이에 새 소켓을 만듭니다.
- 서버는 들어오는 요청이 정상적인 HTTP 요청임을 확인하고 응답을 보냅니다.
- 클라이언트 B가 응답을 받으면 소켓이 닫힙니다.
- 클라이언트 C는 webSocket으로 업그레이드하기위한 HTTP 요청으로 포트 80에서 동일한 서버에 연결합니다.
- 서버는 webSocket 업그레이드 요청에 yes로 응답하고 클라이언트와 서버 모두이 소켓 의 프로토콜 을 webSocket 프로토콜 로만 전환합니다.
- 이 시점에서 통신 할 수있는 webSocket 프로토콜을 사용하는 두 개의 오픈 소켓이 있으며 서버는 여전히 일반 HTTP 요청이거나 webSocket 프로토콜에 대한 업그레이드 요청 일 수있는 새 연결을 수락하고 있습니다.
따라서 서버는 항상 포트 80에서 새 연결을 수락하고 있으며 이러한 새 연결은 일반 HTTP 요청이거나 webSocket 프로토콜로 업그레이드 (따라서 webSocket 연결 시작) 요청 인 HTTP 요청 일 수 있습니다. 그리고이 모든 작업이 진행되는 동안 이미 설정된 webSocket 연결은 webSocket 프로토콜을 사용하여 자체 소켓을 통해 통신합니다.
webSocket 연결 및 통신 체계는 다음과 같은 특성을 갖도록 매우 신중하게 설계되었습니다.
- 새 포트가 필요하지 않았습니다. 들어오는 포트 (가장 일반적으로 포트 80)는 일반 HTTP 요청과 webSocket 통신 모두에 사용할 수 있습니다.
- 새로운 포트가 필요하지 않았기 때문에 방화벽이나 기타 네트워킹 인프라의 변경은 "일반적으로"필요하지 않았습니다. HTTP 트래픽을 예상하는 일부 프록시 또는 캐시는 webSocket 프로토콜 트래픽을 처리 (또는 방지)하기 위해 수정해야 할 수 있으므로 항상 그런 것은 아닙니다.
- 동일한 서버 프로세스가 HTTP 요청과 webSocket 요청을 모두 쉽게 처리 할 수 있습니다.
- HTTP 쿠키 및 / 또는 기타 HTTP 기반 인증 수단은 webSocket 연결 설정 중에 사용될 수 있습니다.
추가 질문에 대한 답변 :
1) 왜 80을 기본 포트로 선택합니까? 디자이너가 WebSocket 통신을 전송 수준의 관점에서 일반 HTTP 통신처럼 보이게 만들고 싶습니까? (즉, 서버 포트는 좋은 오래된 80입니다).
예, 바로 위에있는 내 포인트 1-4를 참조하십시오. webSocket은 기존 HTTP 채널을 통해 설정할 수 있으므로 일반적으로 네트워킹 인프라 변경이 필요하지 않습니다. 기존 HTTP 서버가 단순히 webSocket 지원을 추가 할 수 있기 때문에 새로운 서버 나 서버 프로세스가 필요하지 않다는 점을 덧붙이고 싶습니다.
2) 서버에서 프로토콜 이동이 어떻게 일어나는지 상상하려고합니다. HTTP 또는 WebSocket 트래픽을 처리하기위한 다른 소프트웨어 모듈이 있다고 생각합니다. 첫 번째 서버는 HTTP 모듈을 사용하여 일반 HTTP 요청을 처리합니다. 업그레이드 요청을 찾으면 WebSocket 모듈을 사용하도록 전환합니다.
Different server architectures will handle the division between webSocket packets and HTTP requests differently. In some, webSocket connections might even be forwarded off to a new process. In others, it may just be a different event handler in the same process that is registered for incoming packet traffic on the socket which is now been switched over to the webSocket protocol. This is entirely dependent upon the web server architecture and how it chooses to process webSocket traffic. A developer implementing the server end of a webSocket app will most likely select an existing webSocket implementation that is compatible with their particular web server architecture and then write code that works within that framework.
In my case, I selected the socket.io library that works with node.js (which is my server architecture). That library gives me an object that supports events for newly connecting webSockets and then a set of other events for reading incoming messages or sending outgoing messages. The details of the initial webSocket connection are all handled by the library and I don't have to worry about any of that. If I want to require authentication before the connection is established, the socket.io library has a way for me to plug that in. I can then receive messages from any client, send messages to any single client or broadcast info to all clients. I'm mostly using it for broadcast to keep some info in a web page "live" so that web page display is always current. Anytime the value changes on the server, I broadcast the new value to all connected clients.
To answer your question: simultaneous Websocket and HTTP connections to port 80 are handled...
Exactly the same way simultaneous HTTP connections to port 80 are handled!
That means: Upon satisfactory TCP handshake, the service listening on serviceip:80 proceeds to spawn a new process or thread and handover all the communications for that connection to it (or just serves the request by executing the callback associated with that event as the asynchronous nodejs does, as jfriend00 correctly pointed out).
Then waits or handles the next incoming request in queue.
If you want to know what part HTTP 1.1 and the UPGRADE request play on all of this, this MSDN article on it leaves it very clear:
The WebSocket Protocol has two parts: a handshake to establish the upgraded connection, then the actual data transfer. First, a client requests a websocket connection by using the "Upgrade: websocket" and "Connection: Upgrade" headers, along with a few protocol-specific headers to establish the version being used and set-up a handshake. The server, if it supports the protocol, replies with the same "Upgrade: websocket" and "Connection: Upgrade" headers and completes the handshake. Once the handshake is completed successfully, data transfer begins.
Only Websocket services are usually not built into the web server so not really intended to listen in port 80, just accessible through it thanks to the web server's transparent forwarding. Apache Web server does that using mod_proxy_wstunnel.
Of course you can also have a web server with a built in web sockets implementation: Apache Tomcat, for example.
The main thing here is: Websocket protocol is not HTTP. It serves a different purpose. It is an independent application-layer communication protocol also built on top of TCP (although TCP isn't necessary the requirement, but a transport layer protocol that fits the requirements of the Websockets application layer protocol).
A Websocket service is a PARALLEL service running along with a web server service.
It uses the Websocket protocol, for which modern web browsers have support, implementing the client part of the interface.
You set up or build a Websocket service in order to establish persistent, non-HTTP connections between Websocket clients (usually web browsers) and that service.
The main advantage is: The Websocket service can SEND a message to the client whenever it needs to ("one of you buddies has connected!" "your team just scored a goal!"), instead of having to wait for the client's explicit REQUEST for an update.
You can establish a persistent connection using HTTP 1.1, but HTTP is not meant for anything other than serving a set of resources UPON REQUEST and then close the connection.
Up until recently, before Websockets' support was available in all major browsers, you had only two choices for implementing real time updates on a web application:
Implementing AJAX long polling requests, which is a painful and inefficient process.
Using / building a browser plugin (for example a Java applet support plugin) in order to be able to establish a non-HTTP connection with you updates service, which is more efficient but even more painful than long polling.
In terms of the service's shared listening port (which can be any TCP port, and it doesn't even have to be open to the internet, since most web servers support transparent forwarding of web socket connections), it works exactly as any other TCP service: the service just listens on it and when the TCP handshake is over a TCP socket exists for the service to communicate with the client.
As usual, all connections to a service listening on a particular TCP socket (server_ip:service_TCP_port) will be differentiated when assigned a unique client_ip:client_TCP_port pair, the client_TCP_port being randomly chosen by the client amongst its available TCP ports).
If you are still in doubt about the HTTP->Websocket application protocol handover happening upon Websocket connection handshake and how it doesn't have anything to do with the underlying TCP connection, I refer you to Jan-Philip Gehrcke's answer, which is very clear an instructive and probably what you were actually looking for.
It's quite a simple concept, so let me try to describe it in simple terms in case some other lost soul wants to grasp it without having to read all those long explanations.
Multiple connections
The web server starts listening for connections. This happens:
- The main process of the web server opens a passive socket in state
listen
on port80
, e.g.9.9.9.9:80
(9.9.9.9
is the server IP and80
is the port).
- The main process of the web server opens a passive socket in state
The browser makes a request to port
80
on the server. This happens:The Operating System (in short OS) allocates a random outbound port on the client, say:
1.1.1.1:6747
(1.1.1.1
is the client IP and6747
is the random port).The OS sends a data packet with the source address
1.1.1.1:6747
and destination address9.9.9.9:80
. It goes through various routers and switches and arrives at the destination server.
The server receives the packet. This happens:
The server OS sees that the packet's destination address is one of its own IP addresses and based on the destination port passes it on to the application associated with port
80
.The main process of the web server accepts the connection creating a new active socket. Then it usually forks a new child process, which takes over the active socket. The passive socket stays open to accept new incoming connections.
Now every packet send from the server to the client will have those addresses:
- source:
9.9.9.9:1553
; destination:1.1.1.1:80
And every packet send from the client to the server will have those addresses:
- source:
1.1.1.1:80
; destination:9.9.9.9:1553
HTTP -> WebSocket handshake
HTTP is a text-based protocol. See the HTTP wiki for the list of available commands. The browser sends one of those commands and the web server responds accordingly.
WebSocket is not based on HTTP. It's a binary protocol where multiple streams of messages can be send in both directions at the same time (full-duplex mode). Because of that it would not be possible to establish a WebSocket connection directly without introducing a new HTTP standard, like for example HTTP/2. But that would be only possible if:
WebSocket supported HTTP verbs/requests
There was a new dedicated port different than
80
for WebSocket-specific communication.
The first wasn't in scope for the protocol and the second would break the existing web infrastructure. Because a client/browser can establish multiple HTTP connections with the same server, switching some of them from HTTP to WebSocket is the best of both worlds - keep the same port 80
but allow a different protocol than HTTP. The switch happens through protocol handshake initiated by the client.
ReferenceURL : https://stackoverflow.com/questions/28516962/how-websocket-server-handles-multiple-incoming-connection-requests
'programing' 카테고리의 다른 글
shared_mutex 향상에 해당하는 C ++ 11 (0) | 2021.01.14 |
---|---|
Vim에서 b와 B의 차이점은 무엇입니까? (0) | 2021.01.14 |
"make install"과 "make altinstall"의 세부 사항 차이 (0) | 2021.01.14 |
Xcode 5 오류 CertUIFramework.axbundle (0) | 2021.01.14 |
고유 한 장치 식별 (0) | 2021.01.14 |