Du må være registrert og logget inn for å kunne legge ut innlegg på freak.no
X
LOGG INN
... eller du kan registrere deg nå
Dette nettstedet er avhengig av annonseinntekter for å holde driften og videre utvikling igang. Vi liker ikke reklame heller, men alternativene er ikke mange. Vær snill å vurder å slå av annonseblokkering, eller å abonnere på en reklamefri utgave av nettstedet.
  4 943
Jeg trenger et spesialtilpasset RAT(Remote Administration Tool) så jeg tenkte at jeg kunne finne noe som jeg kunne bruke i vb.net

Jeg fant disse to:
http://msdn2.microsoft.com/en-us/library/bew39x2a.aspx
http://msdn2.microsoft.com/en-us/library/fx6588te.aspx

Det så ut til å fungere med det første, men når jeg skulle sende melding nr.2 til serveren så fikk jeg meldingen:
"Cannot access a disposed object.
Object name: 'System.Net.Sockets.Socket'."

Dette skjer da altså når jeg aktiverer Public Shared Sub Main() for andre gang.
Hva gjør jeg galt?
m0b
m0b's Avatar
DonorAdministrator
Kan sikkert lønne seg om du poster litt av koden du har skrevet. Er det noen spesiell grunn til at du velger asynkron? Det jeg personlig ville gjort var å opprette en socket pr klient som kobler seg til og putte behandlingen av denne i en thread.
Trådstarter
Jeg har hovedsaklig bare kopiert koden i linkene og satt main til oppstartsobjekt. Her er koden til klienten:

Kode

Imports System
Imports System.Net
Imports System.Net.Sockets
Imports System.Threading
Imports System.Text


' State object for receiving data from remote device.

Public Class StateObject
    ' Client socket.
    Public workSocket As Socket = Nothing
    ' Size of receive buffer.
    Public Const BufferSize As Integer = 256
    ' Receive buffer.
    Public buffer(BufferSize) As Byte
    ' Received data string.
    Public sb As New StringBuilder
End Class 'StateObject


Public Class AsynchronousClient
    ' The port number for the remote device.
    Private Const port As Integer = 11000

    ' ManualResetEvent instances signal completion.
    Private Shared connectDone As New ManualResetEvent(False)
    Private Shared sendDone As New ManualResetEvent(False)
    Private Shared receiveDone As New ManualResetEvent(False)

    ' The response from the remote device.
    Private Shared response As String = String.Empty


    Public Shared Sub Main()
        ' Establish the remote endpoint for the socket.
        ' For this example use local machine.
starten:

        Console.ReadLine()
        Dim ipHostInfo As IPHostEntry = Dns.Resolve(Dns.GetHostName())
        Dim ipAddress As IPAddress = ipHostInfo.AddressList(0)
        Dim remoteEP As New IPEndPoint(ipAddress, port)

        ' Create a TCP/IP socket.
        Dim client As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)

        ' Connect to the remote endpoint.
        client.BeginConnect(remoteEP, New AsyncCallback(AddressOf ConnectCallback), client)

        ' Wait for connect.
        connectDone.WaitOne()

        ' Send test data to the remote device.
        Send(client, "This is a test<EOF>")
        sendDone.WaitOne()

        ' Receive the response from the remote device.
        Receive(client)
        receiveDone.WaitOne()

        ' Write the response to the console.
        Console.WriteLine("Response received : {0}", response)

        ' Release the socket.
        client.Shutdown(SocketShutdown.Both)
        client.Close()

        GoTo starten
    End Sub 'Main


    Private Shared Sub ConnectCallback(ByVal ar As IAsyncResult)
        ' Retrieve the socket from the state object.
        Dim client As Socket = CType(ar.AsyncState, Socket)

        ' Complete the connection.
        client.EndConnect(ar)

        Console.WriteLine("Socket connected to {0}", client.RemoteEndPoint.ToString())

        ' Signal that the connection has been made.
        connectDone.Set()
    End Sub 'ConnectCallback


    Private Shared Sub Receive(ByVal client As Socket)

        ' Create the state object.
        Dim state As New StateObject
        state.workSocket = client

        ' Begin receiving the data from the remote device.
        client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, New AsyncCallback(AddressOf ReceiveCallback), state)
    End Sub 'Receive


    Private Shared Sub ReceiveCallback(ByVal ar As IAsyncResult)

        ' Retrieve the state object and the client socket 
        ' from the asynchronous state object.
        Dim state As StateObject = CType(ar.AsyncState, StateObject)
        Dim client As Socket = state.workSocket

        ' Read data from the remote device.
        Dim bytesRead As Integer = client.EndReceive(ar)

        If bytesRead > 0 Then
            ' There might be more data, so store the data received so far.
            state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead))

            ' Get the rest of the data.
            client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, New AsyncCallback(AddressOf ReceiveCallback), state)
        Else
            ' All the data has arrived; put it in response.
            If state.sb.Length > 1 Then
                response = state.sb.ToString()
            End If
            ' Signal that all bytes have been received.
            receiveDone.Set()
        End If
    End Sub 'ReceiveCallback


    Private Shared Sub Send(ByVal client As Socket, ByVal data As String)
        ' Convert the string data to byte data using ASCII encoding.
        Dim byteData As Byte() = Encoding.ASCII.GetBytes(data)

        ' Begin sending the data to the remote device.
        client.BeginSend(byteData, 0, byteData.Length, 0, New AsyncCallback(AddressOf SendCallback), client)
    End Sub 'Send


    Private Shared Sub SendCallback(ByVal ar As IAsyncResult)
        ' Retrieve the socket from the state object.
        Dim client As Socket = CType(ar.AsyncState, Socket)

        ' Complete sending the data to the remote device.
        Dim bytesSent As Integer = client.EndSend(ar)
        Console.WriteLine("Sent {0} bytes to server.", bytesSent)

        ' Signal that all bytes have been sent.
        sendDone.Set()
    End Sub 'SendCallback
End Class 'AsynchronousClient
Og her er koden til serveren:

Kode

Imports System
Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports System.Threading
Imports Microsoft.VisualBasic
Module Module1

    Sub Main()
        AsynchronousSocketListener.Main()
    End Sub

End Module

Public Class StateObject
    ' Client  socket.
    Public workSocket As Socket = Nothing
    ' Size of receive buffer.
    Public Const BufferSize As Integer = 1024
    ' Receive buffer.
    Public buffer(BufferSize) As Byte
    ' Received data string.
    Public sb As New StringBuilder
End Class 'StateObject


Public Class AsynchronousSocketListener
    ' Thread signal.
    Public Shared allDone As New ManualResetEvent(False)

    ' This server waits for a connection and then uses  asychronous operations to
    ' accept the connection, get data from the connected client, 
    ' echo that data back to the connected client.
    ' It then disconnects from the client and waits for another client. 
    Public Shared Sub Main()
        ' Data buffer for incoming data.
        Dim bytes() As Byte = New [Byte](1023) {}

        ' Establish the local endpoint for the socket.
        Dim ipHostInfo As IPHostEntry = Dns.Resolve(Dns.GetHostName())
        Dim ipAddress As IPAddress = ipHostInfo.AddressList(0)
        Dim localEndPoint As New IPEndPoint(ipAddress, 11000)

        ' Create a TCP/IP socket.
        Dim listener As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)

        ' Bind the socket to the local endpoint and listen for incoming connections.
        listener.Bind(localEndPoint)
        listener.Listen(100)

        While True
            ' Set the event to nonsignaled state.
            allDone.Reset()

            ' Start an asynchronous socket to listen for connections.
            Console.WriteLine("Waiting for a connection...")
            listener.BeginAccept(New AsyncCallback(AddressOf AcceptCallback), listener)

            ' Wait until a connection is made and processed before continuing.
            allDone.WaitOne()
        End While
    End Sub 'Main


    Public Shared Sub AcceptCallback(ByVal ar As IAsyncResult)
        ' Get the socket that handles the client request.
        Dim listener As Socket = CType(ar.AsyncState, Socket)
        ' End the operation.
        Dim handler As Socket = listener.EndAccept(ar)

        ' Create the state object for the async receive.
        Dim state As New StateObject
        state.workSocket = handler
        handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, New AsyncCallback(AddressOf ReadCallback), state)
    End Sub 'AcceptCallback


    Public Shared Sub ReadCallback(ByVal ar As IAsyncResult)
        Dim content As String = String.Empty

        ' Retrieve the state object and the handler socket
        ' from the asynchronous state object.
        Dim state As StateObject = CType(ar.AsyncState, StateObject)
        Dim handler As Socket = state.workSocket

        ' Read data from the client socket. 
        Dim bytesRead As Integer = handler.EndReceive(ar)

        If bytesRead > 0 Then
            ' There  might be more data, so store the data received so far.
            state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead))

            ' Check for end-of-file tag. If it is not there, read 
            ' more data.
            content = state.sb.ToString()
            If content.IndexOf("<EOF>") > -1 Then
                ' All the data has been read from the 
                ' client. Display it on the console.
                Console.WriteLine("Read {0} bytes from socket. " + vbLf + " Data : {1}", content.Length, content)
                ' Echo the data back to the client.
                Send(handler, content)
            Else
                ' Not all data received. Get more.
                handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, New AsyncCallback(AddressOf ReadCallback), state)
            End If
        End If
    End Sub
    'ReadCallback

    Private Shared Sub Send(ByVal handler As Socket, ByVal data As String)
        ' Convert the string data to byte data using ASCII encoding.
        Dim byteData As Byte() = Encoding.ASCII.GetBytes(data)

        ' Begin sending the data to the remote device.
        handler.BeginSend(byteData, 0, byteData.Length, 0, New AsyncCallback(AddressOf SendCallback), handler)
    End Sub 'Send


    Private Shared Sub SendCallback(ByVal ar As IAsyncResult)
        ' Retrieve the socket from the state object.
        Dim handler As Socket = CType(ar.AsyncState, Socket)

        ' Complete sending the data to the remote device.
        Dim bytesSent As Integer = handler.EndSend(ar)
        Console.WriteLine("Sent {0} bytes to client.", bytesSent)

        handler.Shutdown(SocketShutdown.Both)
        handler.Close()
        ' Signal the main thread to continue.
        allDone.Set()
    End Sub 'SendCallback
End Class 'AsynchronousSocketListener
Jeg er ikke spesiellt opplyst når det kommer til networking i vb.net, det er derfor jeg bare kopierte inn koden til denne artikkelen. Så det er ingen spesiell grunn til at jeg valgte Asynchronous. Men hvis du har en bedre måte å gjøre det på, så hadde det vært veldig fint om du kunne linke meg til en artikkel eller tutorial som kan hjelpe meg på vei
m0b
m0b's Avatar
DonorAdministrator
Siden jeg nå har poppet ei ekstra pils, så føler jeg meg litt i godlaget. Så jeg har tatt meg den frihet å skrive et lite kjapt eksempel på hvordan man kan skrive et serverapplikasjon.

Starter opp serveren, binder opp mot alle ip-adresser den har på en spesifikk port. Når en klient kobles til legger jeg en referanse til klienten i en global liste. Klientaksepteringen er threadet og looper til applikasjonet blir stengt ned.

En ytterligere tråd er også opprettet. Denne går igjennom den tidligere omtalte globale listen med referanse til klientene som er tilkoblet. For hver klient som er tilkoblet, sendes det en melding. Denne er stemplet med tidspunkt så man lett kan se når meldingen er sendt.

Siden jeg ikke er særlig glad i syntaksen Visual Basic (faktisk hater jeg den), så har jeg skrevet eksemplet i C#. Alle objekter jeg bruker her er også kompatible med VB.NET så det bør være en enkel sak å konvertere eksemplet mitt til VB.NET hvis du skulle føle for det. Ettersom ikke [ code ] funker helt som den skal, bruker jeg [ php ]. Men eksemplet mitt kan også leses til det fulle på http://m0b.pastebin.com/m6b4dc036

Du bør også være klar over at i eksemplet mitt har jeg ikke tatt hånd om klienter som har koblet seg fra. Så referansen til klienten vil føre til at applikasjonet krasjer slik det er nå. Men løsningen på det er veldig enkel; fjern klienter som ikke lengre er tilkoblet fra listen. I tillegg har jeg kun tatt for meg Serverbiten, antar at du selv klarer å produsere noe lignende hvis jeg sier til deg at TcpClient og funksjonen Receive() er det du leter etter for klienten? Trenger vel heller kanskje ikke egentlig å nevne at dette kun er en klasse, så dersom den skal brukes må du deklarere den med konstruktør: Server serve = new Server(); i Program/Main entry i applikasjonet.

Kode

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections;

namespace BroadcastServer
{
    class Server
    {
        // Listener-objektet som gjør dette til en "server" som lytter på innkommende
        // tilkoblinger til en gitt port
        private TcpListener listener;
        
        // Denne dynamiske listen brukes for å holde en oversikt over alle
        // klientene som er tilkoblet
        private List<Socket> clients = new List<Socket>();

        // Dette er meldingen som skal sendes til alle klienter
        string publicMessage = "All resistance is futile!";

        public Server()
        {
            // Start serveren
            Start();
        }

        public void Start()
        {
            // Lytter på alle IP-adresser, på port 2471, og starter lyttingen
            listener = new TcpListener( IPAddress.Any, 2471 );
            listener.Start();

            // Threader Liste()-funksjonen slik at ikke serverapplikasjonet
            // bruker alle ressurser på loopinga i listeneren
            Thread listenThread = new Thread( new ThreadStart( Listen ) );
            listenThread.Start();

            // Starter samtidig også en thread som skal behandle klientene som er tilkoblet
            Thread notifyThread = new Thread( new ThreadStart( NotifyClients ) );
            notifyThread.Start();
        }

        public void NotifyClients()
        {
            while( true )
            {
                if( clients.Count > 0 )
                {
                    // Looper igjennom alle klientene og sender de meldingen
                    foreach( Socket client in this.clients )
                    {
                        // Ønsker at meldingen som sendes ut er litt dynamisk, så 
                        // vi endrer litt på den ved å legge på klokkeslettet da den ble sendt ut
                        string message = DateTime.Now.ToLongTimeString() + ": " + this.publicMessage + Environment.NewLine;

                        // Fordi socketen kun bruker byte-array, må meldingen konverteres
                        byte[] bMessage = Encoding.ASCII.GetBytes( message );

                        // Bruker socketen (klienten) og skriver til den så det ender opp hos klienten
                        client.Send( bMessage );
                    }
                    Console.WriteLine( string.Format( "{0}: Sent message to {1} clients", DateTime.Now.ToLongTimeString(), this.clients.Count ) );
                }
                // Fordi klientene ikke skal bli spammet, sendes meldingen ut
                // hvert femte sekund.
                Thread.Sleep( 5000 );
            }
        }

        public void Listen()
        {
            Console.WriteLine( "{0}: Started listening on socket", DateTime.Now.ToLongTimeString() );

            // Looper evig slik at flere klienter kan opprette tilkobling
            while( true )
            {
                // Aksepter tilkoblingen til en klient som kobler seg til
                Socket socket = listener.AcceptSocket();

                // Når klienten har koblet seg til legger vi en referanse til socketen
                // i den dynamiske clients-lista vår slik at man kan nå den i NofityClients()-funksjonen
                if( socket.Connected )
                {
                    Console.WriteLine( string.Format( "{0}: Client connected", DateTime.Now.ToLongTimeString() ) );
                    this.clients.Add( socket );
                }
            }
        }
    }
}
http://80.65.51.238/~kenwi/server_s.png
Stort


Edit: "Ressistance" staves med to enkle s-er og ikke en dobbel og en enkel.
Sist endret av m0b; 25. april 2008 kl. 21:03.
Trådstarter
Takk for hjelpen, jeg skal sette i gang med å oversette det til vb