現在の私たちの簡単な理解の前には、どのようにパッケージおよびそれらを呼び出すとの関係を簡単に理解しながら、クライアントの要求を構築します。包装方法は、需要を満たすことができないときこれにより、我々はあなた自身のニーズ下層を使用する方法を構築することができます。
今日は、サーバーのリスナーメソッドのいくつかを見て、リスナーメソッドにおおよそ行きます
http.ListenAndServeTLS()
http.ListenAndServe()
net.Listen()
net.ListenPacket()
net.ListenTcp()
net.ListenUnix()
net.ListenUdp()
net.ListenIp()
net.ListenUnixgram()
net.ListenMulticastUDP()
チャートを介してそれらの間の関係を見てみましょう。
図、HTTPリスナーから分かるようnet.Listenは()は、TCPとUnixのカプセル化であるnet.Listen()のカプセル化は、です。HTTPはすべての着信TCPを監視します。すべてのHTTPリスナーは、最終的net.ListenTcp()を達成します。
どのnet.ListenTcp、net.ListenUdp()、net.ListenIP()最終的にinternetSocket()すべてを行きます。
私たちは以下のコードを見てみましょう:
func (sl *sysListener) listenTCP(ctx context.Context, laddr *TCPAddr) (*TCPListener, error) {
fd, err := internetSocket(ctx, sl.network, laddr, nil, syscall.SOCK_STREAM, 0, "listen", sl.ListenConfig.Control)
if err != nil {
return nil, err
}
return &TCPListener{fd}, nil
}
func (sd *sysDialer) doDialTCP(ctx context.Context, laddr, raddr *TCPAddr) (*TCPConn, error) {
fd, err := internetSocket(ctx, sd.network, laddr, raddr, syscall.SOCK_STREAM, 0, "dial", sd.Dialer.Control)
for i := 0; i < 2 && (laddr == nil || laddr.Port == 0) && (selfConnect(fd, err) || spuriousENOTAVAIL(err)); i++ {
if err == nil {
fd.Close()
}
fd, err = internetSocket(ctx, sd.network, laddr, raddr, syscall.SOCK_STREAM, 0, "dial", sd.Dialer.Control)
}
if err != nil {
return nil, err
}
return newTCPConn(fd), nil
}
コードの比較により、着信internetSocketが異なる識別子は、ダイヤルと聞きます。ダイアルながらTCP聞く論理的に多少異なることがありますが、文字盤を見て、UDP聴けば、彼らはまったく同じロジックがあります。
すべてのこのナンセンスを言って、サーバーを実装する方法で見てみましょうが、最初は私たちの最も人気の高いサービスです。http:
http.ListenAndServe()、だけにしてその上に着信コールポートをリッスン、聞くことは非常に簡単なルートを構築するために必要なビルドWebサービスを行きます:
http.HandleFunc("/", HelloServer)
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
http.ListenAndServeTLSと基本的にListenAndServeつ以上のキーを渡すと同じ、ちょうど必要性:
http.HandleFunc("/", handler)
http.ListenAndServeTLS(":8081", "server.crt",
"server.key", nil)
HTTP以外のトラブルスポットに対処するために必要なnet.Listenのために、彼は手動でハンドルクライアント要求と実装サービスにあなたを必要とします。
func chkError(err error) {
if err != nil {
log.Fatal(err);
}
}
//单独处理客户端的请求
func clientHandle(conn net.Conn) {
defer conn.Close();
conn.Write([]byte("hello " + time.Now().String()));
}
func main() {
//创建一个TCP服务端
tcpaddr, err := net.ResolveTCPAddr("tcp4", "127.0.0.1:8080");
chkError(err);
//监听端口
tcplisten, err2 := net.ListenTCP("tcp", tcpaddr);
chkError(err2);
//死循环的处理客户端请求
for {
//等待客户的连接
conn, err3 := tcplisten.Accept();
//如果有错误直接跳过
if err3 != nil {
continue;
}
//通过goroutine来处理用户的请求
go clientHandle(conn);
}
}