ååã®è¨äºã§WebSocketã«ã¤ãã¦ã®è§£èª¬ãããããå
ã«Socketéä¿¡ã«ã¤ãã¦ã®èª¬æããã¦ããã¹ãã ã¨æã£ãã®ã§ãä»åã¯Socketéä¿¡ã«ã¤ãã¦æ¸ãã
mnagaa.hatenablog.com
ããããã½ã±ããã¨ã¯ï¼
- ãããã¯ã¼ã¯éä¿¡ã«ãããã¨ã³ããã¤ã³ããå®ç¾©ããæ½è±¡çãªæ¦å¿µ
- ã½ã±ããã使ç¨ãããã¨ã§ã¢ããªã±ã¼ã·ã§ã³ããããã¯ã¼ã¯ãä»ãã¦ãã¼ã¿ãéåä¿¡ã§ãã
- ç¹å®ã®ãããã³ã«ï¼TCPãUDPï¼ã«åºã¥ãã¦éä¿¡ãè¡ãããã®ã¤ã³ã¿ãã§ã¼ã¹ãæä¾
ã½ã±ãã
- IPã¢ãã¬ã¹ã¨ãã¼ãçªå·ãé¢é£ã¥ãããã¦ããããã®çµã¿åããã«ãã£ã¦ãç¹å®ã®ãã·ã³ã¨ç¹å®ã®ã¢ããªã±ã¼ã·ã§ã³ãéä¿¡ç¸æãç¹å®ã§ãã
- ã¹ããªã¼ã ã½ã±ããï¼Stream Socketï¼: TCPã使ã£ãä¿¡é ¼æ§ã®ããéä¿¡ã«ä½¿ç¨
- ãããã³ã«ï¼TCP (Transmission Control Protocol)
- ç¹å¾´ï¼ä¿¡é ¼æ§ã®ãããé åºãä¿è¨¼ãããã¼ã¿éä¿¡ãè¡ãããããã¼ã¿ã¯ã¹ããªã¼ã ï¼é£ç¶ãããã¤ãåï¼ã¨ãã¦ããåãããã
- ç¨éï¼HTTPãFTPãSSHãªã©ã®å¤ãã®ã¢ããªã±ã¼ã·ã§ã³ããã®ã½ã±ããã¿ã¤ããå©ç¨
- ãã¼ã¿ã°ã©ã ã½ã±ããï¼Datagram Socketï¼ï¼UDPã使ã£ãéä¿¡é ¼æ§ã®ããéä¿¡ã«ä½¿ç¨
- ãããã³ã«: UDPï¼User Datagram Protocolï¼
- ç¹å¾´: ä¿¡é ¼æ§ã¯ä¿è¨¼ãããããã¼ã¿ã失ãããå¯è½æ§ããããã³ãã¯ã·ã§ã³ã¬ã¹ã®ããããã¼ã¿ã¯ãã±ããåä½ï¼ãã¼ã¿ã°ã©ã ï¼ã§éä¿¡ãããåä¿¡é åºãä¿è¨¼ãããªãã
- ç¨é: DNSã¯ã¨ãªãé³å£°ã»æ åã¹ããªã¼ãã³ã°ãªã©ãä½é
延ãæ±ãããããä¿¡é ¼æ§ãããã»ã©éè¦ã§ãªãå ´åã«ä½¿ç¨ãããã
- IPã¢ãã¬ã¹ï¼éä¿¡ç¸æãä¸æã«èå¥ããããã®ã¢ãã¬ã¹ãIPv4ã§ã¯32ããããIPv6ã§ã¯128ããã
- ãã¼ãçªå·ï¼åããã·ã³ä¸ã§åä½ããè¤æ°ã®ã¢ããªã±ã¼ã·ã§ã³éã§éä¿¡ãåºå¥ããããã«ä½¿ç¨ãããçªå·ããã¼ãçªå·ã¯0~65535ã®ç¯å²ã§ãHTTPãµã¼ãã¼ãªã80ãHTTPSãµã¼ãã¼ãªã443ãªã©ãç¹å®ã®ãµã¼ãã¹ã«å¯¾ãã¦ä¸è¬ã«ä½¿ç¨ããããã¼ãçªå·ãããã0~1023ã®ãã¼ãã¯ã¦ã§ã«ãã¦ã³ãã¼ãã¨å¼ã°ããä¸è¬ã¦ã¼ã¶ã¼ã¯bindãããã¨ãã§ããªã
ç¹å¾´
- ä¿¡é ¼æ§ã®é«ãéä¿¡: TCPã¯ãã¼ã¿ã®éåä¿¡ã«ããã¦ä¿¡é ¼æ§ãéè¦ããããã¼ã¿ã®é åºãå®å
¨æ§ãä¿è¨¼ããããã±ããã失ãããå ´åãé åºãå
¥ãæ¿ãã£ãå ´åã§ãèªåã§åéãåæ§æãè¡ãããã
- æ¥ç¶æå (Connection-Oriented): TCPã¯éä¿¡ãè¡ãåã«ãéä¿¡å
ã¨åä¿¡å
ã®éã§ã3-wayãã³ãã·ã§ã¤ã¯ãã¨å¼ã°ããããã»ã¹ãçµã¦æ¥ç¶ã確ç«ããããã®æ¥ç¶ã«ãã£ã¦ããã¼ã¿ã®éä¿¡ã»åä¿¡ãå®å®çã«è¡ãããã
- ããã¼å¶å¾¡ (Flow Control): TCPã¯éä¿¡é度ãå¶å¾¡ããåä¿¡å´ããã±ãããå¦çã§ããé度ã«åããã¦ãã¼ã¿ãéä¿¡ãããããã«ãããåä¿¡å´ã®ãããã¡ããªã¼ãã¼ããã¼ããã®ãé²ãã
- ã¨ã©ã¼ãã§ãã¯ã¨åé: TCPã¯ãåä¿¡å´ã§ãã¼ã¿ã«èª¤ãããã£ãå ´åãããã±ãããæ¬ è½ããå ´åã«èªåçã«åéãè¦æ±ããä»çµã¿ãåãã¦ããã
- é åºã®ä¿è¨¼: TCPã§ã¯ãéä¿¡ãããã±ãããéä¿¡é åºéãã«ç¸æã«å±ããã¨ãä¿è¨¼ããããå°çé åºãç°ãªã£ãå ´åã§ããTCPã¯ãã¼ã¿ãé©åã«ä¸¦ã¹æ¿ããã
å
¸åçãªç¨é
- HTTP/HTTPS: Webãã©ã¦ã¶ã¨Webãµã¼ãã¼éã®éä¿¡ã¯TCPã使ç¨ãããä¿¡é ¼æ§ã®é«ãéä¿¡ãå¿
è¦ãªããã
- FTP: ãã¡ã¤ã«è»¢éãããã³ã«ãTCPã使ç¨ãããã¡ã¤ã«ãå®å
¨ãã¤æ£ç¢ºã«è»¢éãããããã«ãã¦ããã
- SMTP: ã¡ã¼ã«ã®éåä¿¡ãTCPã使ç¨ããã
ç¹å¾´
- ä¿¡é ¼æ§ã®ãªãéä¿¡: UDPã¯ãTCPã¨ã¯ç°ãªãããã¼ã¿ã®ä¿¡é ¼æ§ãé åºã¯ä¿è¨¼ããªãããã±ããã失ãããããé çªãå
¥ãæ¿ãã£ã¦ããåéãé åºã®åæ§æã¯è¡ãããªãã
- ã³ãã¯ã·ã§ã³ã¬ã¹ (Connectionless): UDPã§ã¯ããã¼ã¿ãéä¿¡ããåã«æ¥ç¶ã確ç«ããæé ã¯ä¸è¦ããã±ãããéä¿¡ãããå³åº§ã«éä¿¡ãå®äºããããããã£ã¦ããªã¼ãã¼ããããå°ãªããé
延ãå°ãªãéä¿¡ãå®ç¾ã§ããã
- ã¨ã©ã¼ãã§ãã¯ã¯éå®ç: UDPã¯ãã±ããã®ã¨ã©ã¼ãã§ãã¯ãè¡ãããã¨ã©ã¼ãæ¤åºãããå ´åã«ãã®ãã±ãããç ´æ£ããã®ã¿ã§ãåéè¦æ±ã¯è¡ããªãã
- 軽éã»é«é: ä¿¡é ¼æ§ãç ç²ã«ãã代ããã«ãUDPã¯é常ã«é«éã§ãä½é
延ã®éä¿¡ãå¯è½ã
å
¸åçãªç¨é
- DNSã¯ã¨ãª: DNSã§ã¯ãçãè¦æ±ã¨å¿çãè¡ãããã«UDPã使ç¨ããããå¿çã®åéã¯ã¢ããªã±ã¼ã·ã§ã³å´ã§å®è£
ããããã¨ãå¤ãã
- VoIP: é³å£°ããããªé話ã®ããã«ããªã¢ã«ã¿ã¤ã æ§ãæ±ããããããå¤å°ã®ãã¼ã¿æ失ã許容ãããã¢ããªã±ã¼ã·ã§ã³ã§UDPã使ç¨ãããã
- ãªã³ã©ã¤ã³ã²ã¼ã : ã²ã¼ã ã®ãªã¢ã«ã¿ã¤ã ãªæä½ããã¼ã¿è»¢éã§ã¯ãå¤å°ã®ãã¼ã¿æ失ãé åºã®éãããããä½é
延ãåªå
ãããããUDPã使ãããã
ç¹å¾´ |
TCP |
UDP |
ãããã³ã«ã®ç¨®é¡ |
æ¥ç¶æåï¼ã³ãã¯ã·ã§ã³åï¼ |
ã³ãã¯ã·ã§ã³ã¬ã¹ï¼éæ¥ç¶åï¼ |
ä¿¡é ¼æ§ |
é«ãï¼ãã¼ã¿ã®é åºä¿è¨¼ãåéï¼ |
ä½ãï¼ä¿¡é ¼æ§ãªããåéãªãï¼ |
æ¥ç¶ç¢ºç« |
å¿
è¦ï¼3-wayãã³ãã·ã§ã¤ã¯ï¼ |
ä¸è¦ |
ãã¼ã¿ã®é åºä¿è¨¼ |
ãã |
ãªã |
ããã¼å¶å¾¡ |
ãã |
ãªã |
ã¨ã©ã¼ãã§ãã¯ã¨åé |
ãã |
ã¨ã©ã¼ãã§ãã¯ã®ã¿ï¼åéãªãï¼ |
ãªã¼ãã¼ããã |
é«ã |
ä½ã |
é
延 |
æ¯è¼çé«ã |
ä½ã |
主ãªç¨é |
ãã¡ã¤ã«è»¢éãWebéä¿¡ãEã¡ã¼ã« |
DNSã¯ã¨ãªãã¹ããªã¼ãã³ã°ããªã³ã©ã¤ã³ã²ã¼ã |
éä¿¡æé
TCPã½ã±ããã®éä¿¡æé
ã³ãã¯ã·ã§ã³æåã®ããã3-way ãã³ãã·ã§ã¤ã¯ï¼SYN, SYN-ACK, ACKï¼ã§æ¥ç¶ã確ç«ãããã¼ã¿ã®éåä¿¡ãçµããã¨4-way ãã³ãã·ã§ã¤ã¯ã§æ¥ç¶ãçµäºããã
sequenceDiagram
participant Client
participant Server
Server->>Server: socket() ã½ã±ããä½æ
Server->>Server: bind() IPã¢ãã¬ã¹ã¨ãã¼ãçªå·ããã¤ã³ã
Server->>Server: listen() æ¥ç¶è¦æ±ãå¾
æ©
Client->>Server: æ¥ç¶è¦æ± (SYN)
Server->>Client: æ¥ç¶åãå
¥ã (SYN-ACK)
Client->>Server: ACK (æ¥ç¶ç¢ºç«)
Client->>Server: send() ãã¼ã¿éä¿¡
Server->>Client: recv() ãã¼ã¿åä¿¡
Server->>Client: send() ãã¼ã¿éä¿¡
Client->>Server: recv() ãã¼ã¿åä¿¡
Client->>Server: close() æ¥ç¶çµäºè¦æ±
Server->>Client: close() æ¥ç¶çµäº
3-way ãã³ãã·ã§ã¤ã¯
- ã¯ã©ã¤ã¢ã³ãã¯ãµã¼ãã¼ã«SYNï¼åæï¼ãã±ãããéä¿¡ããã
- ãµã¼ãã¼ã¯SYN-ACKï¼åæã»å¿çï¼ãã±ããã§å¿çããã
- ã¯ã©ã¤ã¢ã³ããACKï¼å¿çï¼ãã±ãããéä¿¡ãã¦ãæ¥ç¶ã確ç«ãããã
ãã¼ã¿éåä¿¡
æ¥ç¶ã確ç«ãããã¨ãã¯ã©ã¤ã¢ã³ãã¨ãµã¼ãã¼éã§ãã¼ã¿ãéåä¿¡ãããã
ãã¼ã¿ã®éä¿¡ã¯ãã±ããã«åå²ãããTCPã¯åä¿¡å´ãæ£ããé åºã§ãã¼ã¿ãåæ§ç¯ãããã¨ãä¿è¨¼ããã
4-way ãã³ãã·ã§ã¤ã¯ï¼æ¥ç¶çµäºï¼
éä¿¡ãçµããã¨ãã¯ã©ã¤ã¢ã³ãã¾ãã¯ãµã¼ãã¼ãæ¥ç¶ãçµäºããããã«4-way ãã³ãã·ã§ã¤ã¯ãè¡ãããã
- ã¯ã©ã¤ã¢ã³ãã¯FINãã±ãããéä¿¡ãã¦æ¥ç¶çµäºãè¦æ±ããã
- ãµã¼ãã¼ãACKãã±ããã§å¿çããæ¥ç¶çµäºãæ¿èªããã
- ãµã¼ãã¼ã¯èªåã®çµäºæºåãã§ããå¾ãFINãã±ãããéä¿¡ããã
- ã¯ã©ã¤ã¢ã³ããACKãã±ãããè¿ããæ¥ç¶ãçµäºããã
UDPã½ã±ããã®éä¿¡æé
ã³ãã¯ã·ã§ã³ã¬ã¹ã®ãããæ¥ç¶ã®ç¢ºç«ãçµäºã®æé ã¯ãªãããã¼ã¿ãéä¿¡ãã¦çµããã
sequenceDiagram
participant Client
participant Server
Client->>Server: ãã¼ã¿éä¿¡ (sendto)
Server->>Client: ãã¼ã¿åä¿¡ (recvfrom)
Note over Client,Server: ã³ãã¯ã·ã§ã³ã¬ã¹ã®ãããã³ãã·ã§ã¤ã¯ãªã
Client->>Server: ãã¼ã¿éä¿¡ (sendto)
Server->>Client: ãã¼ã¿åä¿¡ (recvfrom)
Note over Client,Server: éä¿¡çµäº
ã³ã¼ãä¾
TCPãµã¼ãã¼
package main
import (
"fmt"
"net"
"os"
)
func main() {
listener, err := net.Listen("tcp", "127.0.0.1:8080")
if err != nil {
fmt.Println("Error starting TCP server:", err)
os.Exit(1)
}
defer listener.Close()
fmt.Println("TCP server is listening on 127.0.0.1:8080")
for {
conn, err := listener.Accept()
if err != nil {
fmt.Println("Error accepting connection:", err)
continue
}
go handleConnection(conn)
}
}
func handleConnection(conn net.Conn) {
defer conn.Close()
buf := make([]byte, 1024)
n, err := conn.Read(buf)
if err != nil {
fmt.Println("Error reading from connection:", err)
return
}
fmt.Printf("Received message: %s\n", string(buf[:n]))
}
TCPã¯ã©ã¤ã¢ã³ã
package main
import (
"fmt"
"net"
"os"
)
func main() {
conn, err := net.Dial("tcp", "127.0.0.1:8080")
if err != nil {
fmt.Println("Error connecting to server:", err)
os.Exit(1)
}
defer conn.Close()
message := "Hello, Server!"
_, err = conn.Write([]byte(message))
if err != nil {
fmt.Println("Error sending message:", err)
return
}
fmt.Println("Message sent to server")
}
UDPãµã¼ãã¼
package main
import (
"fmt"
"net"
"os"
)
func main() {
addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:8080")
if err != nil {
fmt.Println("Error resolving address:", err)
os.Exit(1)
}
conn, err := net.ListenUDP("udp", addr)
if err != nil {
fmt.Println("Error starting UDP server:", err)
os.Exit(1)
}
defer conn.Close()
fmt.Println("UDP server is listening on 127.0.0.1:8080")
buf := make([]byte, 1024)
for {
n, addr, err := conn.ReadFromUDP(buf)
if err != nil {
fmt.Println("Error reading from connection:", err)
continue
}
fmt.Printf("Received message from %s: %s\n", addr.String(), string(buf[:n]))
}
}
UDPã¯ã©ã¤ã¢ã³ã
package main
import (
"fmt"
"net"
"os"
)
func main() {
addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:8080")
if err != nil {
fmt.Println("Error resolving address:", err)
os.Exit(1)
}
conn, err := net.DialUDP("udp", nil, addr)
if err != nil {
fmt.Println("Error connecting to server:", err)
os.Exit(1)
}
defer conn.Close()
message := "Hello, UDP Server!"
_, err = conn.Write([]byte(message))
if err != nil {
fmt.Println("Error sending message:", err)
return
}
fmt.Println("Message sent to UDP server")
}