言語を行きます。 小規模なクライアントサーバーアプリケーション

このコードは自習用に書かれています。 素材を統合するために、作業について少しコメントすることにしました。

私はすぐに言わなければなりません:私はコンパイルされた言語で書きませんでした。



アプリケーションは何をしますか



[k]-クライアント

[c]-サーバー

1.確立されたTCP接続を介して、[k]は公開キーrsaを転送します。

2.受け入れられた公開鍵を使用して、[c]メッセージを暗号化して送信します[to]

3. [k]はメッセージを復号化して表示します。



コンソールでは次のように表示されます。

画像





サーバー



package main
      
      





必要なパッケージをインポートします

 import( //   / .      "fmt" //      Unix networks sockets, including TCP/IP, UDP . //      TCP . "net" //        "os" //   / "bufio" //           "crypto/rsa" //       "crypto/rand" //     sha1 "crypto/sha1" //           "strconv" //      "big" )
      
      



パッケージへのアクセスは、ドットを介した名前によって行われます。

例: fmt



Println()



os



Exit()



など

必要なパッケージ名がわからない場合は、コードの一番上の行でパッケージソースを確認できます。

たとえば、 crypto / rsaの場合、 6行目のrsa.go

goinstallコマンドを使用すると、他の開発者からパッケージをインストールできます。

この場合、「bitbucket.org/user/project」、「github.com/user/project」、または「project.googlecode.com/hg」のようなものをインポートします



必要な定数を宣言する

 const( //  tcp  tcpProtocol = "tcp4" //   rsa  keySize = 1024 //       readWriterSize = keySize/8 )
      
      







接続「c」とこの接続「pubK」へのキーを一緒に保持するには、remoteConnデータ型を構造体として宣言します。

 type remoteConn struct { c *net.TCPConn pubK *rsa.PublicKey }
      
      



変数の型の前のアスタリスク「*」は、変数が宣言された型のデータへの参照であることを意味します

net.TCPConnは、TCP接続情報の構造を含むデータ型です。

rsa.PublicKey-データ型。 送信メッセージの暗号化に必要です。



慣れるために、次のように表示されるエラーを処理します。

この関数は、タイプがos.Errorである単一のerr



値を取ります。

この場合、 osパッケージのエラータイプ( os.Error



)を使用しています。

 func checkErr(err os.Error){ if err != nil { //    fmt.Println(err) //   os.Exit(1) } }
      
      







タイプnet.TCPAddrの構造への参照となるグローバル変数listenAddr



を宣言します

 var listenAddr = &net.TCPAddr{IP: net.IPv4(192,168,0,4), Port: 0}
      
      



net.TCPAddrの前のアンパサンド "&"は、このタイプへの参照を返します。

この場合の「ポート:0」は、すべての空きポートを意味します。



次の関数は、接続と公開鍵を組み合わせて、この接続をremoteConn



構造に暗号化します。

そして、値ではなく、 remoteConn



へのリンクを返します。

 func getRemoteConn(c *net.TCPConn) *remoteConn{ return &remoteConn{c: c, pubK: waitPubKey(bufio.NewReader())} }
      
      



bufio.NewReader()



-接続「c」からバイトバッファーを作成します。 戻り値の型*bufio.Reader



*bufio.Reader



へのリンク)

waitPubKey()



-「クライアント」から特定のシーケンスでPublicKey



が送信されることを期待する



この関数は、バッファー( *bufio.Reader



)への参照を受け取ります。このバッファーには、接続 "c"からのすべてのバイトが含まれます

 //      rsa.PublicKey func waitPubKey(buf *bufio.Reader) (*rsa.PublicKey) { //     line, _, err := buf.ReadLine(); checkErr(err) //    line - []byte ( ) //      <code><b>line</b></code>   if string(line) == "CONNECT" { //         ,       line, _, err := buf.ReadLine(); checkErr(err) //  PublicKey.N //   rsa.PublicKey pubKey := rsa.PublicKey{N: big.NewInt(0)} // pubKey.N == 0 //  pubKey.N big.Int http://golang.org/pkg/big/#Int //       pubKey.N big.Int pubKey.N.SetString(string(line), 10) //  SetString()  2 : // string(line) -      // 10 -       // (2 , 8 , 10 , 16  ...) //       pubKey.E line, _, err = buf.ReadLine(); checkErr(err) //   strconv    string   int pubKey.E, err = strconv.Atoi(string(line)); checkErr(err) //    rsa.PublicKey return &pubKey } else { //        .  : //    fmt.Println("Error: unkown command ", string(line)) os.Exit(1) //   } return nil }
      
      







次の関数は、 remoteConn



型の変数を参照するためのメソッドです

一連のアクションを実行して、メッセージを暗号化して送信します。

 func (rConn *remoteConn) sendCommand(comm string) { //   eComm, err := rsa.EncryptOAEP(sha1.New(), rand.Reader, rConn.pubK, []byte(comm), nil) // sha1.New()    hash.Hash //       sha512.New() sha256.New() ... // rand.Reader   io.Reader       //    /dev/unrandom   Linux  CryptGenRandom API   Windows // rConn.pubK -       func waitPubKey // []byte(comm) -   comm    ([]byte) checkErr(err) //    //        rConn.c.Write(eComm) // rConn.c  ? - net.TCPConn     Write() // http://golang.org/pkg/net/#TCPConn.Write }
      
      







以下は、以前に宣言された関数で動作し、最終的に「クライアント」サーバー名とグリーティングを異なる言語で送信する関数です。

 func listen() { //     l, err := net.ListenTCP(tcpProtocol, listenAddr); checkErr(err) //    fmt.Println("Listen port: ", l.Addr().(*net.TCPAddr).Port) // l == *net.TCPListener ==     // .Addr() http://golang.org/pkg/net/#TCPListener.Addr ==   *net.TCPListener   "" // net.Addr http://golang.org/pkg/net/#Addr        TCPAddr - *net.TCPAddr //    Network()  String() c, err := l.AcceptTCP(); checkErr(err) //             // AcceptTCP() -   *net.TCPListener http://golang.org/pkg/net/#TCPListener.AcceptTCP //     fmt.Println("Connect from:", c.RemoteAddr()) //  3     fmt.Print[f|ln]()    // 1. c.RemoteAddr() // 2. c.RemoteAddr().(*net.TCPAddr) // 3. c.RemoteAddr().String() //     : fmt.Println(), fmt.Print(), fmt.Printf()    String() //       //             rConn := getRemoteConn() //     rConn.sendCommand("Go Language Server v0.1 for learning") rConn.sendCommand("!") rConn.sendCommand("і!") rConn.sendCommand("і!") rConn.sendCommand("Hello!") rConn.sendCommand("Salut!") rConn.sendCommand("ハイ!") rConn.sendCommand("您好!") rConn.sendCommand("안녕!") rConn.sendCommand("Hej!") }
      
      







これでサーバーのレビューが完了しました。

 func main() { listen() }
      
      







お客様



 package main import( "fmt" "net" "os" "bufio" "crypto/rsa" "crypto/rand" "crypto/sha1" "strconv" ) const( tcpProtocol = "tcp4" keySize = 1024 readWriterSize = keySize/8 ) func checkErr(err os.Error){ if err != nil { fmt.Println(err) os.Exit(1) } } var connectAddr = &net.TCPAddr{IP: net.IPv4(192,168,0,2), Port: 0} //             func connectTo() *net.TCPConn{ //   "Enter port:"      fmt.Print("Enter port:") //        "%d" fmt.Scanf("%d", &connectAddr.Port) // Scanf           fmt.Println("Connect to", connectAddr) //     c ,err := net.DialTCP(tcpProtocol, nil, connectAddr); checkErr(err) return c } //      PublicKey func sendKey(c *net.TCPConn, k *rsa.PrivateKey) { //       PublicKey c.Write([]byte("CONNECT\n")) //  N  *big.Int c.Write([]byte(k.PublicKey.N.String() + "\n")) // String()  *big.Int  string //  E  int c.Write([]byte(strconv.Itoa(k.PublicKey.E) + "\n")) // strconv.Itoa()  int  string // []byte()  ""    } //       //    func getBytes(buf *bufio.Reader, n int) []byte { //  n  bytes, err:= buf.Peek(n); checkErr(err) //  n  skipBytes(buf, n) return bytes } // ,     func skipBytes(buf *bufio.Reader, skipCount int){ for i:=0; i<skipCount; i++ { buf.ReadByte() } } func main() { //    c := connectTo() //       "c" buf := bufio.NewReader() //           k, err := rsa.GenerateKey(rand.Reader, keySize); checkErr(err) //     sendKey(c, k) //        for { //      cryptMsg := getBytes(buf, readWriterSize) //   msg, err := rsa.DecryptOAEP(sha1.New(), rand.Reader, k, cryptMsg, nil) //    checkErr(err) //    fmt.Println(string(msg)) } }
      
      







コメントが1つもないソースは、次の場所にあります。

code.google.com/p/learning-go-language/source/browse



All Articles