Pertanyaan Simulasikan koneksi tcp di Go


Di Go, koneksi TCP (net.Conn) adalah io.ReadWriteCloser. Saya ingin menguji kode jaringan saya dengan mensimulasikan koneksi TCP. Ada dua persyaratan yang saya miliki:

  1. data yang akan dibaca disimpan dalam string
  2. setiap kali data ditulis, saya ingin itu disimpan dalam beberapa jenis buffer yang dapat saya akses nanti

Apakah ada struktur data untuk ini, atau cara mudah untuk membuatnya?


5
2017-12-29 21:07


asal


Jawaban:


Mengapa tidak menggunakan bytes.Buffer? Itu adalah io.ReadWriter dan memiliki String metode untuk mendapatkan data yang disimpan. Jika Anda perlu membuatnya menjadi io.ReadWriteCloser, Anda dapat menentukan jenis Anda sendiri:

type CloseableBuffer struct {
    bytes.Buffer
}

dan tentukan a Close metode:

func (b *CloseableBuffer) Close() error {
    return nil
}

3
2017-12-30 17:39



EDIT: Saya telah menggulirkan jawaban ini ke dalam paket yang membuat semuanya menjadi lebih sederhana - lihat di sini: https://github.com/jordwest/mock-conn


Sementara solusi Ivan akan bekerja untuk kasus-kasus sederhana, perlu diingat bahwa koneksi TCP sebenarnya adalah dua buffer, atau lebih tepatnya pipa. Sebagai contoh:

 Server   |   Client
 ---------+---------
  reads <===  writes
 writes ===>  reads

Jika Anda menggunakan buffer tunggal yang dibaca dan ditulis oleh server, Anda dapat mengakhiri dengan server yang berbicara dengan dirinya sendiri.

Berikut ini solusi yang memungkinkan Anda untuk lulus MockConn ketik sebagai ReadWriteCloser ke server. Itu Read, Write dan Close fungsi cukup proxy melalui fungsi pada ujung server dari pipa.

type MockConn struct {
    ServerReader *io.PipeReader
    ServerWriter *io.PipeWriter

    ClientReader *io.PipeReader
    ClientWriter *io.PipeWriter
}

func (c MockConn) Close() error {
    if err := c.ServerWriter.Close(); err != nil {
        return err
    }
    if err := c.ServerReader.Close(); err != nil {
        return err
    }
    return nil
}

func (c MockConn) Read(data []byte) (n int, err error)  { return c.ServerReader.Read(data) }
func (c MockConn) Write(data []byte) (n int, err error) { return c.ServerWriter.Write(data) }

func NewMockConn() MockConn {
    serverRead, clientWrite := io.Pipe()
    clientRead, serverWrite := io.Pipe()

    return MockConn{
        ServerReader: serverRead,
        ServerWriter: serverWrite,
        ClientReader: clientRead,
        ClientWriter: clientWrite,
    }
}

Ketika mengejek koneksi 'server', cukup lewati MockConn di tempat di mana Anda akan menggunakan net.Conn (ini jelas mengimplementasikan ReadWriteCloser hanya antarmuka, Anda dapat dengan mudah menambahkan metode dummy untuk LocalAddr() dll jika Anda perlu mendukung penuh net.Conn antarmuka)

Dalam tes Anda, Anda dapat bertindak sebagai klien dengan membaca dan menulis ke ClientReader dan ClientWriter bidang sesuai kebutuhan:

func TestTalkToServer(t *testing.T) {
    /*
     * Assumes that NewMockConn has already been called and
     * the server is waiting for incoming data
     */

    // Send a message to the server
    fmt.Fprintf(mockConn.ClientWriter, "Hello from client!\n")

    // Wait for the response from the server
    rd := bufio.NewReader(mockConn.ClientReader)
    line, err := rd.ReadString('\n')

    if line != "Hello from server!" {
        t.Errorf("Server response not as expected: %s\n", line)
    }
}

5
2018-06-23 08:12



Tidak tahu apakah ini ada ketika pertanyaan itu ditanyakan, tetapi Anda mungkin ingin net.Pipe() yang menyediakan Anda dengan dua dupleks penuh net.Conn contoh yang terkait satu sama lain


2
2017-11-29 18:58