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

このコードは自習用に書かれています。 素材を統合するために、作業について少しコメントすることにしました。
私はすぐに言わなければなりません:私はコンパイルされた言語で書きませんでした。

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


[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

Source: https://habr.com/ru/post/J126461/


All Articles