Red de conocimiento informático - Material del sitio web - Cómo utilizar canalizaciones con nombre para copiar archivos entre dos hosts en la LAN

Cómo utilizar canalizaciones con nombre para copiar archivos entre dos hosts en la LAN

Hay muchas formas de copiar archivos entre dos hosts en una LAN. La "canalización con nombre" presentada aquí es un mecanismo de comunicación entre procesos relativamente confiable que se puede usar en la misma computadora. También se puede utilizar entre diferentes procesos en diferentes computadoras. Puede ser unidireccional o bidireccional. Windows NT, Windows 2000, Windows 95 y Windows 98 lo admiten y también están disponibles en Unix. . Se implementa en los sistemas operativos de red de servidores Microsoft LAN Manager e IBM LAN.

Las canalizaciones con nombre utilizan el redirector MSNP (Microsoft Network Provider) para que las aplicaciones puedan utilizar este mecanismo para transmitir datos en la red sin conocer los detalles del protocolo de red. Utiliza la interfaz "Named Pipe File System" y su denominación está en formato UNC (Convención de nomenclatura universal):

\\ServerName\Pipe\[pipename]

\\ServerName especifica el servidor en el que se creó la canalización con nombre. ServerName puede ser un nombre de computadora real o un punto decimal (".") para indicar que se creó en esta máquina. \Pipe es un caso codificado (Hardcode) A; -cadena insensible que indica que se trata de un nombre de tubería. El nombre del archivo pertenece a NPFS; [nombre de tubería] es el nombre de tubería personalizado real, que debe ser único en el servidor especificado anteriormente, el nombre puede contener directorios de varios niveles, pero el. El nombre del directorio no debe ser el nombre de una tubería ya creada, por ejemplo:

\\.\Pipe\xyPipe'Este es un nombre de tubería legal

\\.\Pipe\ xyPipe\Pipe' no es un nombre de tubería legal, porque el directorio anterior \\.\Pipe\xyPipe es un nombre de tubería ya creado.

\\.\Pipe\xxyPipe\Pipe’ Este también es un nombre de archivo legal

Las canalizaciones con nombre tienen dos modos de comunicación básicos: modo byte y modo mensaje. En el modo de bytes, los datos se transmiten en la tubería en forma de un flujo de bytes y no hay límites entre los datos en las operaciones de escritura y lectura de la tubería, la unidad básica de operación es el flujo de bytes, es decir, el bloque de datos. que es adecuado para transmitir datos de gran capacidad; en el modo de mensaje, los datos se basan en mensajes discontinuos como unidad de transmisión básica. En las operaciones de escritura y lectura de canales, los mensajes también se operan en unidades. Es adecuado para transmitir pequeñas cantidades de datos. Debido a que los tamaños de archivos actuales suelen ser cientos de K o incluso mayores, el programa opta por utilizar el modo byte.

La siguiente es una introducción detallada a la función CreateNamedPipe(). El prototipo C de esta función es el siguiente:

HANDLE CreateNamedPipe(

LPCTSTR lpName, // puntero al nombre de la tubería

DWORD dwOpenMode, // modo de apertura de la tubería

DWORD dwPipeMode, // modos específicos de la tubería

DWORD nMaxInstances, // máximo número de instancias

DWORD nOutBufferSize, // tamaño del búfer de salida, en bytes

DWORD nInBufferSize, // tamaño del búfer de entrada, en bytes

DWORD nDefaultTimeOut, / / tiempo de espera, en milisegundos

LPSECURITY_ATTRIBUTES lpSecurityAttributes // puntero a los atributos de seguridad

);

lpName: es el nombre de la canalización con nombre mencionada anteriormente. .

dwOpenMode: Hay tres modos para abrir canalizaciones con nombre: PIPE_ACCESS_DUMPLEX (bidireccional), PIPE_ACCESS_INBOUND (entrada) y PIPE_ACCESS_OUTBOUND (salida). Estos indicadores también se pueden combinar con algunos modos de seguridad y control de E/S adicionales. Se utilizan combinaciones constantes; consulte MSDN para obtener más detalles.

dwPipeMode: Es el modo de transmisión de tubería. Hay dos tipos de PIPE_TYPE_BYTE (modo byte) y PIPE_TYPE_MESSAGE (modo de mensaje) mencionados anteriormente. Se puede usar en combinación con las constantes PIPE_READMODE_BYTE y PIPE_READMODE_MESSAGE. modo de lectura del cliente. Puede usar la combinación PIPE_TYPE_MESSAGE y PIPE_READMODE_BYTE para especificar que el remitente envíe datos a la canalización en modo de mensaje y que el receptor pueda leer cualquier número de bytes a la vez. Tenga en cuenta que PIPE_TYPE_BYTE y PIPE_READMODE_MESSAGE no se pueden usar en combinación. Esto hará que la llamada a la función CreateNamedPipe() falle, porque el modo de bytes no tiene límites y los límites del mensaje no se pueden determinar cuando el extremo receptor lee en modo de mensaje.

nMaxInstances: el identificador de instancia de conexión más grande de la canalización, que va de 1 a 255.

nOutBufferSize y nInBufferSize especifican el tamaño de los buffers de entrada y salida de la canalización respectivamente. Si se establece en 0, se utiliza el tamaño predeterminado del sistema.

nDefaultTimeOut establece el tiempo máximo en milisegundos que el cliente debe esperar para establecer una conexión con la canalización nombrada.

LpSecurityAttruibutes es un descriptor de seguridad. Configurarlo en Nulo significa usar el descriptor predeterminado del sistema y el identificador no se puede heredar.

Cabe señalar que en la operación de escritura de la canalización con nombre en el programa, solo se puede escribir un máximo de 64 K bytes de datos a la vez.

El siguiente es el. programa del lado del servidor:

(en módulo):

Función de declaración pública CreateNamedPipe Lib "kernel32" Alias ​​​​"CreateNamedPipeA" (ByVal lpName As String, ByVal dwOpenMode As Long, ByVal dwPipeMode Mientras, ByVal nMaxInstances Mientras, ByVal nOutBufferSize Mientras, ByVal nInBufferSize Mientras, ByVal nDefaultTimeOut Mientras, ByVal lpSecurityAttributes Mientras) Mientras

Función de declaración pública ConnectNamedPipe Lib "kernel32" (ByVal hNamedPipe Como Long, ByVal lplong As Long) As Long

Función de declaración pública ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lplong As Long) As Long

Función de declaración pública WriteFile Lib "kernel32" (ByVal hFile mientras, lpBuffer como cualquiera, ByVal nNumberOfBytesToWrite mientras, lpNumberOfBytesWritten mientras, ByVal lplong mientras) Mientras

Declaración pública Función CloseHandle Lib "kernel32" (ByVal hObject As Long) Mientras

Función de declaración pública WaitNamedPipe Lib "kernel32" Alias ​​"WaitNamedPipeA" (ByVal lpNamedPipeName As String, ByVal nTimeOut As Long) Mientras

Función de declaración pública CreateFile Lib "kernel32" Alias ​​​​" CreateFileA" (ByVal lpFileName como cadena, ByVal dwDesiredAccess mientras, ByVal dwShareMode mientras, ByVal lpSecurityAttributes mientras, ByVal dwCreationDisposition mientras, ByVal dwFlagsAndAttributes mientras, ByVal hTemplateFile As Long) As Long

Función de declaración pública DisconnectNamed

Pipe Lib "kernel32" (ByVal hNamedPipe As Long) Mientras

Función de declaración pública GetFileSize Lib "kernel32" (ByVal hFile As Long, lpFileSizeHigh As Long) Mientras tanto Public Const PIPE_ACCESS_DUPLEX = &H3

Const pública PIPE_ACCESS_INBOUND = &H1

Const pública PIPE_ACCESS_OUTBOUND = &H2

Const pública PIPE_CLIENT_END = &H0

Const pública PIPE_NOWAIT = &H1

Const pública PIPE_READMODE_BYTE = &H0

Const pública PIPE_READMODE_MESSAGE = &H2

Const pública PIPE_SERVER_END = &H1

Const pública PIPE_TYPE_BYTE = &H0

Const pública PIPE_TYPE_MESSAGE = &H4

Const pública PIPE_UNLIMITED_INSTANCES = 255

Const pública PIPE_WAIT = &H0

Const pública FILE_SHARE_READ = &H1

Const pública FILE_SHARE_WRITE = &H2

Const pública GENERIC_READ = &H80000000

Const pública GENERIC_WRITE = &H40000000

Const pública GENERIC_EXECUTE = &H20000000

Const pública GENERIC_ALL = &H1000000 0

Const pública OPEN_EXISTING = 3

Const pública ERROR_PIPE_BUSY = 231&

Const pública ERROR_PIPE_CONNECTED = 535&

Const pública ERROR_PIPE_LISTENING = 536&

Public Const ERROR_PIPE_NOT_CONNECTED = 233&

Public Const ERROR_NO_DATA = 232& Public Const BufferSize& = 51200

Public hNamePipe&, hFile&, strNamePipe$ Hay tres botones en el formulario, a saber "Crear" canalización con nombre "(CreateNPipe), "Enviar archivo" (SendFile), "Cerrar canalización con nombre" (CloseNamePipe), y también hay un CommonDia en la ventana

control de registro, denominado "CDlg1".

Código en el formulario:

Atenuar outBuffer() como byte, inBuffer() como byte, BytesRead mientras, BytesWrite mientras, BytesReaded mientras, BytesWrited mientras

Private Sub CloseNamePipe_Click( )

DisconnectNamedPipe hNamePipe

CloseHandle hNamePipe

CreateNPipe.Enabled = True

SendFile.Enabled = False

CloseNamePipe.Enabled = False

End Sub Private Sub CreateNPipe_Click()

Dim hReturn&

strNamePipe = "\\.\pipe\xyvanPipe"

hNamePipe = CreateNamedPipe(strNamePipe, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE o PIPE_READMODE_BYTE, 1, 0, 0, 0, 0)

Si hNamePipe <> -1 entonces

hReturn = ConnectNamedPipe( hNamePipe, 0)

Si hReturn = 0 Entonces

MsgBox "¡La tubería no puede esperar a la conexión del cliente!", vbInformation O vbOKOnly

Descargarme

Else

Label1 = "¡Conectado al cliente!"

End If

CreateNPipe.Enabled = False

SendFile.Enabled = True

CloseNamePipe.Enabled = True

Else

MsgBox "¡No se puede crear una canalización con nombre!", vbInformation o vbOKOnly

Descargarme

Finalizar si

Finalizar sub privado Form_Load()

Con CDlg1

.CancelError = True

.DialogTitle = "Seleccione los archivos a transferir:"

.filename = ""

.Filter = "Todos los archivos (*.*)|*.* "

.Flags = cdlOFNExplorer O cdlOFNFileMustExist O cdlOFNPathMustExist

.InitDir = "d:\"

Finalizar con

SendFile.Enabled = False

CloseNamePipe.Enabled = False

End Sub Private Sub Form_QueryUnload(Cancelar como entero, UnloadMode como entero)

DisconnectNamedPipe hNam

ePipe

CloseHandle hFile

CloseHandle hNamePipe

Fin Sub Private Sub SendFile_Click()

En caso de error Reanudar siguiente

Dim strFileName$, lpFileSize&, lpFileSizeHigh&, lpFileSizeLeast&, byteEnd() como byte

Dim strShortName$

CDlg1.ShowOpen

Si Err.Number = 32755 Entonces Salir de Sub

strFileName = CDlg1.filename

strShortName = CDlg1.FileTitle

hFile = CreateFile(strFileName, GENERIC_READ, FILE_SHARE_READ o FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0 , 0)

Si hFile = -1 Entonces

MsgBox "No se puede abrir el archivo" & strFileName, vbInformation o vbOKOnly

Salir de Sub

Finalizar si

lpFileSize = GetFileSize(hFile, lpFileSizeHigh)

Si lpFileSize = 0 Entonces

MsgBox "El tamaño del archivo es cero, ¡no es necesario enviarlo! ", vbInformation O vbOKOnly

CloseHandle hFile

Salir Sub

End If

lpFileSizeLeast = lpFileSize byteEnd() = StrConv(strShortName, vbFromUnicode)

ReDim outBuffer(UBound(byteEnd))

ByteCopy byteEnd, outBuffer

WriteFile hNamePipe, byteEnd(0), UBound(byteEnd) + 1, BytesWrited, 0 'Enviar nombre de archivo corto

ReDim inBuffer(5)

ReadFile hNamePipe, inBuffer(0), 6, BytesReaded, 0 'Leer información de conversación del cliente

If StrConv(inBuffer, vbUnicode) = "Cancelar" Entonces

MsgBox "¡El cliente seleccionó cancelar al guardar y el envío finaliza! ", vbInformation O vbOKOnly

CloseHandle hFile

Salir Sub

End If

Label1.Caption = "Transmitiendo..."

Mientras lpFileSize > 0

Si lpFileSize > BufferSize entonces

ReDim outBuffer(BufferSize - 1)

ReadF

ile hFile, outBuffer(0), BufferSize, BytesReaded, 0

WriteFile hNamePipe, outBuffer(0), BytesReaded, BytesWrited, 0

Else

ReDim outBuffer (lpFileSize - 1)

ReadFile hFile, outBuffer(0), lpFileSize, BytesReaded, 0

WriteFile hNamePipe, outBuffer(0), lpFileSize, BytesWrited, 0

End If

lpFileSize = lpFileSize - BytesReaded

ReadFile hNamePipe, inBuffer(0), 6, BytesReaded, 0

Wend byteEnd() = StrConv( "EOF", vbFromUnicode)

ReDim outBuffer(UBound(byteEnd))

ByteCopy byteEnd, outBuffer

WriteFile hNamePipe, outBuffer(0), 3, BytesWrited , 0

CloseHandle hFile

Label1 = "¡Transferencia de archivo completada!"

End Sub

Public Sub ByteCopy(bySrc() As Byte, byDes() como byte)

Atenuar I mientras

For i = LBound(bySrc) a UBound(bySrc)

byDes(i) = bySrc(i)

Next

End Sub Por lo demás, agrégame en QQ y te engordaré y te daré 83989024