Ada enam langkah untuk membuat pipa bernama server:
- Membuat token keamanan untuk pipa untuk membolehkan akses ke (untuk membuat Pipa bernama tersedia untuk proses dengan menciptakan token keamanan dengan Discretionary Access Control List (DACL) yang memiliki entri nol di dalamnya).
- Membuat pipa bernama.
- Hubungi ConnectNamedPipe untuk memblokir sampai tersambung.
- Panggilan ReadFile dan/atau WriteFile untuk berkomunikasi melalui pipa.
- Memanggil DisconnectNamedPipe setelah proses selesai menggunakan pipa.
- Baik CloseHandle bernama pipa, atau kembali ke langkah 4.
- Hubungi CreateFile untuk mendapatkan pegangan untuk bernama pipa.
- Panggilan ReadFile dan/atau WriteFile untuk berkomunikasi melalui pipa.
- Panggilan CloseHandle filehandle yang dibuat di CreateFile.
Contoh berikut menunjukkan cara membuat bernama pipa Server dan Klien. Menerapkan hanya fungsi paling dasar yang diperlukan untuk melakukan Jadi, dengan jumlah minimal pengecekan error. Program yang berfungsi penuh harus memeriksa kembali nilai-nilai dari API yang disebut, daripada dengan asumsi mereka adalah sukses.
Bernama pipa Server
- Membuat proyek baru. Form1 dibuat secara default.
- Tambahkan kode berikut ke bentuk:
Option Explicit Private Const szPipeName = "\\.\pipe\bigtest" Private Const BUFFSIZE = 20000 Private BigBuffer(BUFFSIZE) As Byte, pSD As Long Private sa As SECURITY_ATTRIBUTES Private hPipe As Long Private Sub Form_Click() Dim i As Long, dwOpenMode As Long, dwPipeMode As Long Dim res As Long, nCount As Long, cbnCount As Long For i = 0 To BUFFSIZE - 1 'Fill an array of numbers BigBuffer(i) = i Mod 256 Next i 'Create the NULL security token for the pipe pSD = GlobalAlloc(GPTR, SECURITY_DESCRIPTOR_MIN_LENGTH) res = InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION) res = SetSecurityDescriptorDacl(pSD, -1, 0, 0) sa.nLength = LenB(sa) sa.lpSecurityDescriptor = pSD sa.bInheritHandle = True 'Create the Named Pipe dwOpenMode = PIPE_ACCESS_DUPLEX Or FILE_FLAG_WRITE_THROUGH dwPipeMode = PIPE_WAIT Or PIPE_TYPE_MESSAGE Or PIPE_READMODE_MESSAGE hPipe = CreateNamedPipe(szPipeName, dwOpenMode, dwPipeMode, _ 10, 10000, 2000, 10000, sa) Do 'Wait for a connection, block until a client connects res = ConnectNamedPipe(hPipe, ByVal 0) 'Read/Write data over the pipe cbnCount = 4 res = ReadFile(hPipe, nCount, LenB(nCount), cbnCount, ByVal 0) If nCount <> 0 Then If nCount > BUFFSIZE Then 'Client requested nCount bytes nCount = BUFFSIZE 'but only send up to 20000 bytes End If 'Write the number of bytes requested res = WriteFile(hPipe, BigBuffer(0), nCount, cbnCount, ByVal 0) 'Make sure the write is finished res = FlushFileBuffers(hPipe) End If 'Disconnect the NamedPipe res = DisconnectNamedPipe(hPipe) Loop Until nCount = 0 'Close the pipe handle CloseHandle hPipe GlobalFree (pSD) End End Sub
- Membuat modul baru dan menambahkan pernyataan berikut:
Option Explicit Public Const FILE_ATTRIBUTE_NORMAL = &H80 Public Const FILE_FLAG_NO_BUFFERING = &H20000000 Public Const FILE_FLAG_WRITE_THROUGH = &H80000000 Public Const PIPE_ACCESS_DUPLEX = &H3 Public Const PIPE_READMODE_MESSAGE = &H2 Public Const PIPE_TYPE_MESSAGE = &H4 Public Const PIPE_WAIT = &H0 Public Const INVALID_HANDLE_VALUE = -1 Public Const SECURITY_DESCRIPTOR_MIN_LENGTH = (20) Public Const SECURITY_DESCRIPTOR_REVISION = (1) Type SECURITY_ATTRIBUTES nLength As Long lpSecurityDescriptor As Long bInheritHandle As Long End Type Public Const GMEM_FIXED = &H0 Public Const GMEM_ZEROINIT = &H40 Public Const GPTR = (GMEM_FIXED Or GMEM_ZEROINIT) Declare Function GlobalAlloc Lib "kernel32" ( _ ByVal wFlags As Long, ByVal dwBytes As Long) As Long Declare Function GlobalFree Lib "kernel32" (ByVal hMem As Long) As Long Declare Function CreateNamedPipe Lib "kernel32" Alias _ "CreateNamedPipeA" ( _ ByVal lpName As String, _ ByVal dwOpenMode As Long, _ ByVal dwPipeMode As Long, _ ByVal nMaxInstances As Long, _ ByVal nOutBufferSize As Long, _ ByVal nInBufferSize As Long, _ ByVal nDefaultTimeOut As Long, _ lpSecurityAttributes As Any) As Long Declare Function InitializeSecurityDescriptor Lib "advapi32.dll" ( _ ByVal pSecurityDescriptor As Long, _ ByVal dwRevision As Long) As Long Declare Function SetSecurityDescriptorDacl Lib "advapi32.dll" ( _ ByVal pSecurityDescriptor As Long, _ ByVal bDaclPresent As Long, _ ByVal pDacl As Long, _ ByVal bDaclDefaulted As Long) As Long Declare Function ConnectNamedPipe Lib "kernel32" ( _ ByVal hNamedPipe As Long, _ lpOverlapped As Any) As Long Declare Function DisconnectNamedPipe Lib "kernel32" ( _ ByVal hNamedPipe As Long) As Long Declare Function WriteFile Lib "kernel32" ( _ ByVal hFile As Long, _ lpBuffer As Any, _ ByVal nNumberOfBytesToWrite As Long, _ lpNumberOfBytesWritten As Long, _ lpOverlapped As Any) As Long Declare Function ReadFile Lib "kernel32" ( _ ByVal hFile As Long, _ lpBuffer As Any, _ ByVal nNumberOfBytesToRead As Long, _ lpNumberOfBytesRead As Long, _ lpOverlapped As Any) As Long Declare Function FlushFileBuffers Lib "kernel32" ( _ ByVal hFile As Long) As Long Declare Function CloseHandle Lib "kernel32" ( _ ByVal hObject As Long) As Long
- Simpan bentuk.
A. Bernama pipa klien
- Membuat proyek baru. Form1 dibuat secara default.
- Tambahkan kontrol berikut untuk bentuk:
Type Name Caption/Default Value ---- ---- --------------------- TextBox cbBytes 500 CommandButton cmdCallNamedPipe Call Named Pipe TextBox txtReceive
- Tambahkan kode berikut ke bentuk:
Option Explicit Private Const szPipeName = "\\.\pipe\bigtest", BUFFSIZE = 20000 Private Declare Function CallNamedPipe Lib "kernel32" Alias _ "CallNamedPipeA" ( _ ByVal lpNamedPipeName As String, _ lpInBuffer As Any, _ ByVal nInBufferSize As Long, _ lpOutBuffer As Any, _ ByVal nOutBufferSize As Long, _ lpBytesRead As Long, _ ByVal nTimeOut As Long) As Long Private Sub cmdCallNamedPipe_Click() Dim res As Long, myStr As String, i As Long, cbRead As Long Dim numBytes As Long, bArray() As Byte, temp As String numBytes = cbBytes.Text If cbBytes.Text < 0 Then MsgBox "Value must be at least 0.", vbOKOnly Exit Sub End If If numBytes > BUFFSIZE Then numBytes = BUFFSIZE End If ReDim bArray(numBytes) 'Build the return buffer 'Call CallNamedPipe to do the transaction all at once res = CallNamedPipe(szPipeName, numBytes, LenB(numBytes), _ bArray(0), numBytes, _ cbRead, 30000) 'Wait up to 30 seconds for a response If res > 0 Then temp = Format(bArray(0), " 000") For i = 1 To cbRead - 1 If (i Mod 16) = 0 Then temp = temp & vbCrLf temp = temp & " " & Format(bArray(i), "000") Next i txtReceive.Text = temp Else MsgBox "Error number " & Err.LastDllError & _ " attempting to call CallNamedPipe.", vbOKOnly End If End Sub
- Perhatikan bahwa jika server berjalan pada mesin selain di mana klien adalah, Anda perlu untuk mengubah '.' di szPipeName variabel untuk nama mesin server.
- Simpan bentuk. Untuk menguji kode di atas, pertama mulai server dan klik di mana saja bentuk. Aplikasi server sekarang menghalangi dan akan muncul untuk tergantung, tapi benar-benar menunggu untuk client untuk tersambung. Kemudian mulai klien aplikasi dan klik "Panggilan Named Pipe." Klien harus mengirimkan nilai 500 ke server, yang akan menjawab dengan 500 bytes of data. Kamu bisa Tetapkan nilai dalam kotak teks cbBytes dari 0 ke 20000 byte. Untuk menghentikan server, hanya mengirim 0 (nol) dari klien. Klien dapat menerima kesalahan 233 (ERROR_PIPE_NOT_CONNECTED), tapi ini normal.
Perbaikan lain untuk sampel mungkin termasuk penggunaan IO penyelesaian Port dan/atau Non-Blocking membaca dan menulis menggunakan tumpang tindih IO. Kamu bisa menemukan informasi lebih lanjut tentang subjek ini dalam Microsoft Platform SDK.
Tidak ada komentar:
Posting Komentar