従来のソケットプログラミング
Go言語でネットワークプログラミングを行う場合、従来のネットワークプログラミングよりも簡潔です。
TCPプロトコルに基づくネットワークサービスを例にとると、C言語でネットワークプログラムを作成する場合、クライアントとサーバーの実装プロセスは通常次のようになります。
サーバーの観点から、コードの記述は次のステップに分けられます。
- ソケットの確立とバインド:最初に、サーバーは
socket()
関数を使用 してネットワークソケットを確立し、次にそのbind()
関数を使用 してソケットに指定されたIPとポートをバインドします。 - 要求の監視:次に、サーバーは
listen()
関数を使用して 、IPとポートをバインドするクライアントの要求を監視します。 - 接続の受信:要求があり、3ウェイハンドシェイクによって接続が正常に確立された場合は、この
accept()
機能を使用し て接続を受信および処理します。 - リクエストの処理とレスポンスの送信:サーバー
read()
は、write()
関数を介して上記の確立された接続からクライアントから送信されたリクエストデータを読み取り、処理後に関数を介して クライアントにレスポンスデータを送信します。
クライアントの観点から、コードの記述は次のステップに分けられます。
- ソケットの確立:クライアントは、
socket()
関数を使用 してネットワークソケットを確立します。 - 接続を確立します。次に、
connect()
関数を呼び出して IPとポート番号を渡し、指定されたサーバーネットワークプログラムとの接続を確立します。 - 要求の送信と応答の受信:接続が正常に確立された後、クライアントは
write()
関数を介してサーバーにデータを送信し、 関数を使用read()
してサーバーから応答を受信できます。
UDPプロトコルに基づくネットワークサービスの一般的なプロセスも同じですが、サーバーとクライアントの間に接続を確立する必要はありません。
Go言語の標準ライブラリは、このプロセスを抽象化してカプセル化します。使用するプロトコルや接続の形式に関係なく、net.Dial()
関数を呼び出すだけで、コードの記述量が大幅に簡素化されます。以下の関数を見てみましょう。使用法。
Dial()関数
Dial()
関数のプロトタイプは次のとおりです。
func Dial(network, address string) (Conn, error) {
var d Dialer
return d.Dial(network, address)
}
network
パラメータは、(のような着信ネットワークプロトコルを示す tcp
、udp
など)を、address
パラメータが入ってくるIPアドレスまたはドメイン名を示し、ポート番号はオプションです。あなたはそれを指定する必要がある場合は、の形でアドレスまたはドメイン名に従ってください":"十分です。接続が成功した場合、関数は接続オブジェクトを返しますerror
。それ以外の場合、関数はを返します 。
いくつかの一般的なプロトコルの呼び出しメソッドを見てみましょう。
1. TCP接続:
conn, err := net.Dial("tcp", "192.168.10.10:80")
2. UDP接続:
conn, err := net.Dial("udp", "192.168.10.10:8888")
3. ICMP接続(プロトコル名を使用):
conn, err := net.Dial("ip4:icmp", "www.xueyuanjun.com")
注:これip4
はIPv4を意味し、対応するもの ip6
はIPv6を意味します。
4. ICMP接続(プロトコル番号を使用):
conn, err := net.Dial("ip4:1", "10.0.0.3")
注:プロトコル番号の意味は、次のリンクから確認できます:http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml。
現時点では、Dial()
この関数は以下のネットワークサポートtcp
プロトコル:tcp4
、tcp6
、udp
、udp4
、udp6
、ip
、ip4
、ip6
、unix
、、unixgram
と unixpacket
次のようにこれらの契約が説明されます:
tcp
:TCPプロトコルを表し、それが基づいているIPプロトコルのバージョンはパラメータのaddress
値に適応します 。tcp4
:IPプロトコルの4番目のバージョンに基づくTCPプロトコルを表します。tcp6
:IPプロトコルの第6版に基づくTCPプロトコルを表します。udp
:UDPプロトコルを表し、それが基づいているIPプロトコルのバージョンはパラメーターのaddress
値に適応します 。udp4
:IPプロトコルの4番目のバージョンに基づくUDPプロトコルを表します。udp6
:IPプロトコルの第6版に基づくUDPプロトコルを表します。unix
:UnixドメインをSOCK_STREAM
ソケットタイプとして表すための内部ソケット通信プロトコル 。unixgram
:UnixドメインをSOCK_DGRAM
ソケットタイプとして表すための内部ソケット通信プロトコル 。unixpacket
:UnixドメインをSOCK_SEQPACKET
ソケットタイプとして表すための内部ソケット通信プロトコル 。
接続が正常に確立されると、データを送受信できます。データを送信するとき は、接続オブジェクトconn
のWrite()
メソッドを使用し、データを受信するときはそのメソッドを使用 し ます Read()
。次に、簡単なサンプルプログラムを通じて、Go言語でのネットワークプログラミングの実現について説明します。
TCPサンプルプログラム
TCP接続を確立することで単純なHTTPプロトコルを実装します。HTTPヘッドリクエストをネットワークホストに送信し、ネットワークホストから返された情報を読み取ることで、具体的なコードの実装は次のようになります。
package main
import (
"bytes"
"fmt"
"io"
"net"
"os"
)
func main() {
if len(os.Args) != 2 {
fmt.Fprintf(os.Stderr, "Usage: %s host:port", os.Args[0])
os.Exit(1)
}
// 从参数中读取主机信息
service := os.Args[1]
// 建立网络连接
conn, err := net.Dial("tcp", service)
// 连接出错则打印错误消息并退出程序
checkError(err)
// 调用返回的连接对象提供的 Write 方法发送请求
_, err = conn.Write([]byte("HEAD / HTTP/1.0\r\n\r\n"))
checkError(err)
// 通过连接对象提供的 Read 方法读取所有响应数据
result, err := readFully(conn)
checkError(err)
// 打印响应数据
fmt.Println(string(result))
os.Exit(0)
}
func checkError(err error) {
if err != nil {
fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
os.Exit(1)
}
}
func readFully(conn net.Conn) ([]byte, error) {
// 读取所有响应数据后主动关闭连接
defer conn.Close()
result := bytes.NewBuffer(nil)
var buf [512]byte
for {
n, err := conn.Read(buf[0:])
result.Write(buf[0:n])
if err != nil {
if err == io.EOF {
break
}
return nil, err
}
}
return result.Bytes(), nil
}
上記のコードをテストすると、出力は次のようになります。
以下のため 80
のポート、あなたもすることができます http
置き換えます:
Go言語で記述されたネットワークプログラムの全体的な実装コードは、通信の詳細に注意を払う必要なしに、接続の確立、データの送信、およびデータの受信という非常に単純で明確であることがわかります。さまざまな基礎となるプロトコルの。