Go言語のTCP・UDPソケットプログラミング入門|初心者でもわかるネットワーク通信の基本
生徒
「Go言語で、パソコン同士が直接やり取りする通信ってできるんですか?」
先生
「できます。Go言語ではTCPやUDPという仕組みを使って、ネットワーク通信が行えます。」
生徒
「TCPとかUDPって、聞いたことはありますけど、何が違うんですか?」
先生
「それぞれ特徴があります。まずはソケット通信の基本から説明していきますね。」
1. ソケットプログラミングとは?
ソケットプログラミングとは、ネットワークを通じてデータを送ったり受け取ったりする仕組みを直接扱うプログラミング方法です。
とても難しく聞こえますが、イメージとしては「手紙の通り道」を自分で用意して、文字をやり取りする感じです。
Go言語はネットワーク処理が標準機能として充実しているため、TCPやUDPのソケット通信を比較的簡単に書けます。
2. TCP通信とUDP通信の違い
TCPは、確実にデータを届ける通信方法です。順番通りに届き、途中で失敗するとやり直します。Webサイト閲覧やメールで使われています。
UDPは、速さ重視の通信方法です。多少データが欠けても気にせず送ります。動画配信やゲーム通信でよく使われます。
Go言語では、用途に応じてTCPとUDPを使い分けることが大切です。
3. Go言語でTCPサーバーを作る基本
まずはTCP通信の受け口となるサーバーを作ってみましょう。これは「電話を受ける側」の役割です。
package main
import (
"net"
)
func main() {
listener, _ := net.Listen("tcp", ":8080")
defer listener.Close()
conn, _ := listener.Accept()
defer conn.Close()
}
net.Listenは「この番号で待ちます」という意味です。ここでは8080番ポートで通信を待っています。
4. TCPでデータを送受信してみよう
次に、TCP通信で文字を受け取り、返す簡単な例です。これは「会話」をしている状態です。
buf := make([]byte, 1024)
conn.Read(buf)
conn.Write([]byte("受信しました"))
Readは相手の声を聞く操作、Writeは自分の声を送る操作だと考えると分かりやすいです。
5. Go言語でTCPクライアントを作る
次は、サーバーに接続するクライアント側の例です。こちらは「電話をかける側」です。
package main
import (
"net"
)
func main() {
conn, _ := net.Dial("tcp", "localhost:8080")
defer conn.Close()
conn.Write([]byte("こんにちは"))
}
Dialは「指定した相手に接続する」という意味です。TCP通信の基本形になります。
6. UDP通信の基本的な考え方
UDP通信は、TCPと違って接続という概念がありません。送るときに毎回相手を指定します。
その分、処理が軽く速いですが、確実性は保証されません。Go言語でもUDPはシンプルに扱えます。
7. Go言語でUDP通信を行う例
最後に、UDPでデータを送信する簡単な例です。これは「一方的に声を投げる」イメージです。
package main
import (
"net"
)
func main() {
addr, _ := net.ResolveUDPAddr("udp", "localhost:9000")
conn, _ := net.DialUDP("udp", nil, addr)
defer conn.Close()
conn.Write([]byte("UDP通信"))
}
UDPでは、接続確認をせずにデータを送ります。そのため、リアルタイム性が高い処理に向いています。
まとめ
今回は、Go言語のTCP通信とUDP通信を中心に、ソケットプログラミングとネットワーク通信の基本を学びました。ソケットプログラミングとは、ネットワークを通じて別のパソコンやプログラムとデータを送受信するための仕組みを扱うプログラミングです。Go言語にはネットワーク処理に必要な機能が標準で用意されているため、TCPサーバーやTCPクライアント、UDP通信の基本を比較的短いコードで試すことができます。
ネットワーク通信という言葉を聞くと難しそうに感じますが、最初はサーバーとクライアントがデータをやり取りする仕組みとして考えると理解しやすくなります。サーバーは接続を待つ側、クライアントはサーバーへ接続する側です。TCP通信では、サーバーが待ち受ける場所を用意し、クライアントがそこへ接続して、文字列などのデータを送受信します。
TCPとUDPの違いを最初に理解しておこう
Go言語でネットワークプログラミングを学ぶうえで、最初に整理したいのがTCPとUDPの違いです。どちらもネットワーク上でデータをやり取りするための通信方法ですが、特徴が異なります。
TCPは、相手との接続を確立してからデータをやり取りする通信方法です。送信したデータを順番通りに届けることや、通信中に問題が起きた場合の再送などを重視するため、確実性を求める通信に向いています。記事では、Webサイトの閲覧やメールなどで利用される通信として紹介しました。
一方のUDPは、TCPのような接続を前提とせず、相手へデータを送る方式です。確実に届くことよりも、処理の軽さや速さを重視します。そのため、動画配信やゲーム通信など、多少のデータ欠損よりもリアルタイム性が重要な場面で使われます。
| 比較項目 | TCP | UDP |
|---|---|---|
| 通信の考え方 | 接続してから通信する | 接続を前提とせず送信する |
| 特徴 | 確実性を重視する | 速さを重視する |
| データの順序 | 順番通りに届けることを重視する | 確実な順序を前提としない |
| 向いている用途 | Webやメールなど | 動画やゲーム通信など |
初心者のうちは、確実にデータをやり取りしたいならTCP、リアルタイム性や軽さを重視したいならUDPという大きな違いから覚えるとよいでしょう。
Go言語のTCPサーバーは接続を待つ側
TCP通信を理解するためには、サーバーとクライアントの役割を区別することが重要です。サーバーは、クライアントからの接続を待つ側です。電話に例えると、電話がかかってくるのを待っている側に近いイメージです。
Go言語では、net.Listenを利用してTCP通信の待ち受けを開始できます。待ち受けを始めるときには、どの通信方式を使うのかと、どのポート番号で待つのかを指定します。
package main
import (
"fmt"
"net"
)
func main() {
listener, err := net.Listen("tcp", ":8080")
if err != nil {
fmt.Println("待ち受け開始に失敗しました:", err)
return
}
defer listener.Close()
fmt.Println("TCPサーバーを開始しました")
conn, err := listener.Accept()
if err != nil {
fmt.Println("接続受付に失敗しました:", err)
return
}
defer conn.Close()
fmt.Println("クライアントが接続しました")
}
このサンプルでは、8080番のポートでTCP通信を待っています。net.Listenで待ち受けを開始し、Acceptでクライアントからの接続を受け付けています。Go言語のTCPサーバーを学ぶときは、この待ち受け開始と接続受付の流れを最初に覚えることが大切です。
ポート番号は通信の窓口を表す
TCPサーバーのコードで登場したポート番号も、ネットワーク通信を理解するうえで重要です。パソコンでは複数のネットワークプログラムが同時に動くことがあります。そのため、どのプログラムに通信を届けるのかを区別するためにポート番号が使われます。
記事では8080番のポートを使いました。イメージとしては、一台の建物に複数の窓口があり、それぞれに番号が付いているようなものです。クライアントは接続先となるコンピュータだけではなく、その中のどの窓口へ接続するのかも指定します。
Go言語でTCPやUDPのソケット通信を扱うときには、IPアドレスやホスト名だけでなく、ポート番号も通信相手を決める重要な情報になります。
TCPクライアントはnet.Dialでサーバーへ接続する
サーバーが接続を待つ側なら、クライアントは接続を開始する側です。Go言語ではnet.Dialを使ってTCPサーバーへ接続できます。
記事では、同じパソコン上で動いているTCPサーバーへ接続するためにlocalhostを利用しました。localhostは、自分自身のコンピュータを表す名前として使われます。学習中は一台のパソコンでサーバーとクライアントを別々に動かせるため、TCP通信の練習に便利です。
package main
import (
"fmt"
"net"
)
func main() {
conn, err := net.Dial("tcp", "localhost:8080")
if err != nil {
fmt.Println("サーバーへの接続に失敗しました:", err)
return
}
defer conn.Close()
fmt.Println("サーバーへ接続しました")
_, err = conn.Write([]byte("こんにちは"))
if err != nil {
fmt.Println("送信に失敗しました:", err)
return
}
fmt.Println("データを送信しました")
}
このように、サーバー側で待ち受けを開始し、クライアント側から同じポート番号へ接続することでTCP通信の入り口が完成します。
ReadとWriteでTCPデータを送受信できる
接続ができたら、次に必要になるのがデータの送受信です。Go言語では、接続を表す値に対してReadを使えば受信し、Writeを使えば送信できます。
記事ではReadを相手の声を聞く操作、Writeを自分の声を送る操作として説明しました。ネットワーク通信ではデータをバイトの集まりとして扱うため、文字列を送信するときにもバイト列へ変換して送る形になります。
buf := make([]byte, 1024)
size, err := conn.Read(buf)
if err != nil {
fmt.Println("受信に失敗しました:", err)
return
}
message := string(buf[:size])
fmt.Println("受信内容:", message)
_, err = conn.Write([]byte("受信しました"))
if err != nil {
fmt.Println("返信に失敗しました:", err)
}
受信するときには、受信データを入れるための領域を用意します。記事では千二十四バイト分の領域を用意していました。実際に何バイト受信したかを確認し、その範囲を文字列に変換することで、受け取ったメッセージを扱えます。
TCP通信ではサーバーとクライアントの両方が必要
TCPのソケットプログラミングを学ぶときは、サーバーだけを書いて終わりではありません。サーバーが接続を待ち、クライアントが接続し、クライアントから送信されたデータをサーバーが受信し、必要なら返信するという一連の流れを理解することが大切です。
- サーバーが指定したポート番号で待ち受けを開始する
- クライアントがサーバーへ接続する
- サーバーがクライアントからの接続を受け付ける
- クライアントがデータを送信する
- サーバーがデータを受信する
- 必要に応じてサーバーからクライアントへ返信する
この順番を一つずつ確認すると、TCPソケット通信の仕組みを整理しやすくなります。
deferを使って通信を最後に閉じる
記事のTCPサーバーやTCPクライアントでは、接続後にdeferとCloseを使っていました。ネットワーク接続は、使い終わったら閉じる必要があります。
deferを利用すると、現在の関数が終了するときに指定した処理を実行できます。そのため、接続を作ったあとにCloseを予約しておけば、処理終了時に通信を閉じる流れを作りやすくなります。
TCP通信だけでなくUDP通信でも、作成した接続を最後に閉じることが重要です。Go言語のネットワークプログラミングでは、接続を開始する処理と終了する処理をセットで意識するとよいでしょう。
UDPは接続を前提としない通信
UDP通信は、TCPとは通信の考え方が異なります。記事では、TCPには接続という考え方があり、UDPでは接続確認をせずにデータを送ると説明しました。
TCPではサーバーとクライアントが通信のつながりを作ってからデータをやり取りします。一方でUDPでは、データを送信するときに送り先を指定し、そこへデータを送るという考え方になります。
この違いによって、UDPはTCPよりも処理を軽くしやすく、リアルタイム性を重視する用途に向いています。ただし、送信したデータが必ず相手に届くことを前提にはできません。そのため、用途に応じてTCPとUDPを使い分ける必要があります。
Go言語のUDP通信では送信先のアドレスを指定する
Go言語でUDP通信を行う基本例では、まず送信先となるUDPアドレスを用意し、そのアドレスへデータを送信します。記事ではlocalhostの九千番ポートを送信先としていました。
package main
import (
"fmt"
"net"
)
func main() {
addr, err := net.ResolveUDPAddr("udp", "localhost:9000")
if err != nil {
fmt.Println("UDPアドレスの取得に失敗しました:", err)
return
}
conn, err := net.DialUDP("udp", nil, addr)
if err != nil {
fmt.Println("UDP通信の準備に失敗しました:", err)
return
}
defer conn.Close()
_, err = conn.Write([]byte("UDP通信"))
if err != nil {
fmt.Println("UDP送信に失敗しました:", err)
return
}
fmt.Println("UDPデータを送信しました")
}
このように、UDPでもGo言語のnetパッケージを使って通信処理を記述できます。TCPと同じネットワーク通信でも、使用する関数や通信の考え方が異なる点を比較しながら覚えると理解しやすくなります。
Go言語のnetパッケージがネットワーク通信の基本になる
今回の記事で登場したTCPサーバー、TCPクライアント、UDP通信では、いずれもGo言語のnetパッケージを利用しています。
Go言語はネットワーク処理に必要な標準機能が充実しており、外部の特別なライブラリを用意しなくてもTCPやUDPの基本的なソケットプログラミングを学べます。net.Listen、net.Dial、net.ResolveUDPAddr、net.DialUDPなど、それぞれの役割を理解していくことがネットワークプログラミングの第一歩です。
| 機能 | 主な役割 |
|---|---|
net.Listen |
TCPサーバーで接続を待ち受ける |
Accept |
クライアントからの接続を受け付ける |
net.Dial |
TCPサーバーへ接続する |
Read |
通信相手からデータを受信する |
Write |
通信相手へデータを送信する |
net.ResolveUDPAddr |
UDPの送信先アドレスを用意する |
net.DialUDP |
UDP通信を行うための準備をする |
実際のプログラムではエラー処理も重要
記事内の短いサンプルでは、TCPやUDPの仕組みを分かりやすくするため、エラー処理を簡略化している箇所がありました。しかし実際のGo言語プログラムでは、ネットワーク処理のエラーを確認することが非常に重要です。
例えば、指定したポートを使えない場合、サーバーが起動していない場合、接続に失敗した場合、データの送信や受信に失敗した場合など、ネットワーク通信ではさまざまな理由で処理が失敗する可能性があります。
Go言語では多くのネットワーク関数がエラー情報を返すため、その値を確認して問題があれば適切なメッセージを表示したり、処理を終了したりすることが大切です。TCPやUDPの基本を理解したら、次はエラー処理を含めた安全な通信プログラムを意識するとよいでしょう。
TCPとUDPは用途によって選ぶことが大切
TCPとUDPにはそれぞれ長所があります。そのため、どちらか一方が常に優れているというわけではありません。通信するデータの性質によって選択することが重要です。
送信した情報をできるだけ確実に相手へ届けたい場合はTCPが適しています。例えば、文章や重要なデータを途中で失いたくない通信では、確実性が重要になります。
一方、多少のデータ欠損よりも遅延を少なくしたい場合はUDPが候補になります。記事で紹介した動画配信やゲーム通信のように、現在の情報を素早く送り続けることが重要な処理では、UDPの特徴を活かせます。
TCPは確実性を重視し、UDPは速さやリアルタイム性を重視するという基本を覚えておくと、通信方式を選びやすくなります。
localhostを使えば一台のパソコンでも通信を練習できる
ソケットプログラミングというと複数台のパソコンが必要に思えるかもしれませんが、記事で紹介したようにlocalhostを使えば、自分のパソコンの中でサーバーとクライアントを動かして練習できます。
例えば最初にTCPサーバーを起動して8080番ポートで待ち受け、そのあと別のプログラムとしてTCPクライアントを実行してlocalhostの8080番ポートへ接続します。これだけでも、接続、送信、受信というネットワーク通信の基本的な流れを確認できます。
Go言語初心者がTCPやUDPを学習するときは、最初から複雑なネットワーク環境を用意するよりも、自分のパソコン内で短い文字列を送る練習から始めると理解しやすくなります。
初心者はTCP通信から練習すると流れを理解しやすい
ネットワークプログラミングを初めて学ぶ場合は、まずTCPサーバーとTCPクライアントを作って通信の流れを確認すると分かりやすいでしょう。
サーバーで待つ、クライアントから接続する、文字列を送る、サーバーが受け取る、サーバーから返信するという順番を実際に動かすと、ソケット通信という言葉の意味を具体的に理解できます。
TCP通信の基本が理解できたら、次にUDPの送信を試し、接続を前提とするTCPと、接続を前提としないUDPの違いを比べると理解が深まります。
- ソケットプログラミングはネットワーク上でデータを送受信する仕組みを扱う
- TCPは接続してからデータをやり取りする
- TCPは確実性を重視する通信に向いている
- UDPは接続を前提とせずデータを送る
- UDPは速さやリアルタイム性を重視する通信に向いている
- TCPサーバーはnet.Listenで待ち受けを開始する
- Acceptでクライアントからの接続を受け付ける
- TCPクライアントはnet.Dialでサーバーへ接続する
- Readでデータを受信しWriteでデータを送信する
- UDPでは送信先となるアドレスを指定する
- ポート番号は通信するプログラムの窓口を区別する
- ネットワーク処理ではエラー確認と接続の終了処理も重要になる
Go言語のネットワーク通信は小さなサンプルから理解しよう
Go言語のTCP通信やUDP通信は、最初は専門用語が多く難しく感じるかもしれません。しかし、一つずつ役割を整理すると、それほど複雑ではありません。サーバーは待つ側、クライアントは接続する側、Readは受信、Writeは送信という基本を覚えるだけでも、サンプルコードを読みやすくなります。
さらに、TCPは確実性を重視する通信、UDPはリアルタイム性を重視する通信として比較すると、それぞれの役割を整理できます。実際に短いメッセージを一つ送ってみるだけでも、ネットワーク通信がどのように成立しているのかを実感できます。
Go言語にはnetパッケージが用意されているため、ソケットプログラミングの基本を標準機能だけで学習できます。まずTCPサーバーとTCPクライアントをlocalhostで動かし、そのあとUDP送信を試すという順番で練習すると、ネットワーク通信の基礎を段階的に身につけられます。
TCPやUDPの基礎を理解できると、Web通信やゲーム通信、リアルタイム通信など、普段利用しているさまざまなネットワークサービスの仕組みを理解する土台にもなります。Go言語でネットワークプログラミングを学ぶときは、通信方式の名前だけを暗記するのではなく、どのように接続し、どのようにデータを送受信するのかを実際のコードと結びつけて理解することが大切です。
生徒
「最初はTCPやUDPって難しそうでしたけど、どちらもネットワークでデータを送るための方法なんですね。」
先生
「そうです。ただし通信の考え方が違います。TCPは接続してから確実性を重視して通信し、UDPは接続を前提とせず速さを重視して送信します。」
生徒
「TCPサーバーは、まずポート番号を決めてクライアントからの接続を待つんですよね。」
先生
「そのとおりです。Go言語ではnet.Listenを使って待ち受けを開始し、Acceptでクライアントの接続を受け付けます。」
生徒
「クライアント側はnet.Dialでサーバーへ接続するんでしたね。」
先生
「はい。接続ができたら、Writeで送信してReadで受信できます。まずは短い文字列を送って確認すると分かりやすいですよ。」
生徒
「localhostを使えば、自分のパソコンだけでもサーバーとクライアントの通信を試せるんですね。」
先生
「その方法が初心者にはおすすめです。サーバーを起動したあと、別のクライアントプログラムから同じポートへ接続してみましょう。」
生徒
「UDPの場合はTCPみたいに接続を待ってから送るという考え方ではないんですよね。」
先生
「はい。UDPは送り先を指定してデータを送ります。確実に届くことよりも、軽さやリアルタイム性を重視する通信です。」
生徒
「だからWebやメールのように確実性が大切ならTCP、ゲームや動画のように速さが大切な処理ではUDPが使われることがあるんですね。」
先生
「その違いを理解できれば、TCPとUDPの基本はかなり整理できています。」
生徒
「記事の短いコードではエラー処理を省いているところもありましたが、実際のプログラムでは確認したほうがいいんですよね。」
先生
「もちろんです。接続できない、ポートを使えない、送信や受信に失敗するといったことがあるので、実際の開発ではエラー処理が重要です。」
生徒
「まずはTCPサーバーとTCPクライアントを作って、文字列を一つ送るところから試してみます。」
先生
「それがよいですね。そのあとサーバーから返信する処理やUDP通信も試していけば、Go言語のソケットプログラミングとネットワーク通信の基本がしっかり身についていきますよ。」
この記事を読んだ人からの質問
プログラミング初心者からのよくある疑問/質問を解決します
Go言語のソケットプログラミングとは何ですか?プログラミング初心者でも理解できますか?
Go言語のソケットプログラミングとは、ネットワークを通じてパソコン同士やプログラム同士でデータを送受信する仕組みを扱うプログラミング方法です。難しく感じるかもしれませんが、データを届けるための通り道を用意して、そこを使って文字などの情報をやり取りすると考えると理解しやすくなります。Go言語にはネットワーク通信を扱うための標準機能が用意されているため、初心者でも基本から順番に学習できます。
【超入門】ゼロから始めるGo言語プログラミング:最速で「動くアプリ」を作るマンツーマン指導
「プログラミングの仕組み」が根本からわかる。Go言語でバックエンド開発の第一歩を。
本講座を受講することで、単なる文法の暗記ではなく、「プログラムがコンピュータの中でどう動いているか」という本質的な理解につながります。シンプルながら強力なGo言語(Golang)を通じて、現代のバックエンドエンジニアに求められる基礎体力を最短距離で身につけます。
具体的な開発内容と環境
【つくるもの】
ターミナル(黒い画面)上で動作する「対話型計算プログラム」や、データを整理して表示する「ミニ・ツール」をゼロから作成します。自分の書いたコードが形になる感動を体験してください。
【開発環境】
プロの現場でシェアNo.1のVisual Studio Code (VS Code)を使用します。インストールから日本語化、Go言語用の拡張機能設定まで、現場基準の環境を一緒に構築します。
この60分で得られる3つの理解
「なぜ動くのか」という設定の仕組みを理解し、今後の独学で詰まらない土台を作ります。
データの種類やメモリの概念など、他言語にも通じるプログラミングの本質を学びます。
ただ動くだけでなく、誰が見ても分かりやすい「綺麗なコード」を書くための考え方を伝授します。
※本講座は、将来的にバックエンドエンジニアやクラウドインフラに興味がある未経験者のためのエントリー講座です。マンツーマン形式により、あなたの理解度に合わせて進行します。
初めてのGo言語を一緒に学びましょう!