What's the difference between sockets (stream) vs sockets (datagrams)? Why use one over the other?
[채택된 답변]
오래 전에 저는 두가지 차이점을 설명한 최고의 비유글을 읽었습니다. 저는 불행하게도 이 생각을 낸 저자의 크레딧을 기억하지는 않았지만, 어떻든 간에 비유의 핵심은 제 자신의 지식으로 많이 얻을 수 있었습니다.
그것이 여기에 있습니다:
스트림 소켓은 전화기로 전화할 때와 같습니다 -- 한 쪽에서 전화를 걸때, 다른 쪽에서는 답을 합니다, 당신이 다른 사람에게 "안녕"이라고 말하고 정보를 교환합니다. (이것은 TCP에서 SYN과 ACK에 해당합니다.)
한번은 당신이 이제 다 됐다며, "잘가"라고 말합니다. (이것은 TCP에서 FIN과 ACK에 해당합니다.)
만약 다른 쪽이 "잘가"라는 말을 듣지 못했다면, 그 사람은 예측불가능한 이벤트(클라이언트가 서버에 재연결을 시도하는 것처럼) 이후로 전화를 당신에게 다시 걸 것입니다. 당신이 데이터를 보내고나서 다른 쪽에 도착하지 못한 데이터에 대한 보장입니다. 그리고 데이터가 손상을 입을 것같다는 이유있는 보장이기도 합니다.
데이터 그램 소켓은 반에서 쪽지를 보내는 것과 같습니다. 당신이 쪽지를 보낼 다음 사람에게 간접적으로 보내는 예입니다; 쪽지는 사람과 사람 사이를 여행할 것입니다. 그것의 도착지는 정해지지 않았습니다, 그리고 그것은 시간에 의해 수정될 수 있습니다. 만약 당신이 같은 사람에게 두 개의 쪽지를 보낸다면, 그것들은 당신이 의도하지 않았을 때 도착할 것입니다, 예제로 쪽지의 경로는 같은 반이 아니거나 한 사람이 다른 사람처럼 빨리 쪽지를 받을 수 없다.
그러므로 온전한 상태가 중요하고 정보를 가지고 있을 때 당신은 스트림 소켓을 사용할겁니다. 파일 전송 프로토콜은 여기에서 좋은 예제입니다. 당신이 손상되고 랜덤하게 섞인 내용물이 든 일부 파일을 다운하기를 원치 않다면 말입니다!
당신은 때맞춰 도착하는 것(VoIP 또는 게임 프로토콜을 생각해보자.)이 중요할 때, 당신이 더 높은 스트림의 오버헤드를 원치 않을 때, (이것은 한번에 매우 빠르게 많은 요청에 서버가 많은 응답을 할 수 있도록 DNS가 데이타그램 프로토콜에서 중요하다.) 또는 데이터가 이제 목적지에 도착한다면 당신이 너무 많이 받기를 원치않을 때, 데이터 그램 소켓을 사용한다.
자신만의 data-ordering 메커니즘을 포함한 프로토콜 같은 VoIP/게임의 예에서 확장을 원한다. 그러나 만약 한 패킷이 손상을 입거나 잃었을 때, 당신은 요청을 다시 보낼(당신이 빠른 복구가 필요하면) 스트림 프로토콜(TCP에서)을 기다리는 것을 원치 않을 것이다. TCP는 복구하기 위해 몇분을 가져갈 수 있다, 그리고 게임 또는 VoIP처럼 리얼타임 프로토콜은 3초동안 접근이 불가능하다! UDP처럼 데이타그램 프로토콜을 사용하는 것은 TCP가 하는 것보다 곧 재요청 또는 데이타를 잃는 것을 단순하게 무시하려고 엄청 빠른 이벤트로부터 복구하기 위한 소프트웨어를 허용한다.
VoIP는 데이터를 잃은 것을 단순하게 무시하는 좋은 후보다. -- 한 일행이 빈약한 수신상태를 가진 휴대전화에서 누군가가 이야기 할 때 일어나는 것과 같은 짧은 차이(gap)을 듣는다.
게임 프로토콜은 좀 더 복잡하다. 그렇지만 그 행동은 잃어버린 데이터를 무시하는 것이 일반적이다. (만약 나중에 받는 데이터가 잃은 데이터를 대체한다면), 또는 클라이언트 상태가 서버와 같이 동시에 이뤄지는 것을 보장하는 완벽한 상태 업데이트를 요청하거나 잃어버린 데이터를 재요청한다.
A long time ago I read a great analogy for explaining the difference between the two. I don't remember where I read it so unfortunately I can't credit the author for the idea, but I've also added a lot of my own knowledge to the core analogy anyway. So here goes:
A stream socket is like a phone call -- one side places the call, the other answers, you say hello to each other (SYN/ACK in TCP), and then you exchange information. Once you are done, you say goodbye (FIN/ACK in TCP). If one side doesn't hear a goodbye, they will usually call the other back since this is an unexpected event; usually the client will reconnect to the server. There is a guarantee that data will not arrive in a different order than you sent it, and there is a reasonable guarantee that data will not be damaged.
A datagram socket is like passing a note in class. Consider the case where you are not directly next to the person you are passing the note to; the note will travel from person to person. It may not reach its destination, and it may be modified by the time it gets there. If you pass two notes to the same person, they may arrive in an order you didn't intend, since the route the notes take through the classroom may not be the same, one person might not pass a note as fast as another, etc.
So you use a stream socket when having information in order and intact is important. File transfer protocols are a good example here. You don't want to download some file with its contents randomly shuffled around and damaged!
You'd use a datagram socket when order is less important than timely delivery (think VoIP or game protocols), when you don't want the higher overhead of a stream (this is why DNS is primarily a datagram protocol, so that servers can respond to many, many requests at once very quickly), or when you don't care too much if the data ever reaches its destination.
To expand on the VoIP/game case, such protocols include their own data-ordering mechanism. But if one packet is damaged or lost, you don't want to wait on the stream protocol (usually TCP) to issue a re-send request -- you need to recover quickly. TCP can take up to some number of minutes to recover, and for realtime protocols like gaming or VoIP even three seconds may be unacceptable! Using a datagram protocol like UDP allows the software to recover from such an event extremely quickly, by simply ignoring the lost data or re-requesting it sooner than TCP would.
VoIP is a good candidate for simply ignoring the lost data -- one party would just hear a short gap, similar to what happens when talking to someone on a cell phone when they have poor reception. Gaming protocols are often a little more complex, but the actions taken will usually be to either ignore the missing data (if subsequently-received data supercedes the data that was lost), re-request the missing data, or request a complete state update to ensure that the client's state is in sync with the server's.