Avatar billede agerled Nybegynder
05. maj 2006 - 15:36 Der er 18 kommentarer og
1 løsning

Tcp - er der en nemmere / bedre måde i vs2005?

Hej er der nogen der kan sige må om dette kan gøres bedre / nemmere i vs2005. ??

-------------------- Module1.vb -----------------------

Imports System.Net.Sockets

Module Module1
    Const portNo As Integer = 501
    Dim localAdd As System.Net.IPAddress = System.Net.IPAddress.Parse("10.11.10.50")
    'Dim localAdd As System.Net.IPAddress = System.Net.IPAddress.Parse("127.1.0.0")
    Dim listener As New System.Net.Sockets.TcpListener(localAdd, portNo)

    Sub Main()
        listener.Start()
        While True
            Dim user As New CommandClient(listener.AcceptTcpClient)
        End While
    End Sub
End Module

--------------------------------------------------------

------------------ CommandClient.vb --------------------

Imports System.Net.Sockets

Public Class CommandClient
    '---contains a list of all the clients
    Public Shared AllClients As New Hashtable

    '---information about the client
    Private _client As TcpClient
    Private _clientIP As String
    Private _ClientNick As String
    Private _ClientMachinename As String
    Private _ClientTimestamp As String

    '---used for sending/receiving data
    Private data() As Byte

    '---when a client is connected
    Public Sub New(ByVal client As TcpClient)

        _client = client

        '---get the client IP address
        _clientIP = client.Client.RemoteEndPoint.ToString

        '---add the current client to the hash table
        AllClients.Add(_clientIP, Me)

        '---start reading data from the client in a separate thread
        ReDim data(_client.ReceiveBufferSize - 1)
        _client.GetStream.BeginRead(data, 0, _
          CInt(_client.ReceiveBufferSize), _
          AddressOf ReceiveMessage, Nothing)
    End Sub

    '---send the message to the client
    Public Sub SendMessage(ByVal message As String)
        Try
            '---send the text
            Dim ns As System.Net.Sockets.NetworkStream

            SyncLock _client.GetStream
                ns = _client.GetStream
                Dim bytesToSend As Byte() = _
                    System.Text.Encoding.ASCII.GetBytes(message)
                ns.Write(bytesToSend, 0, bytesToSend.Length)
                ns.Flush()
            End SyncLock

        Catch ex As Exception
            Console.WriteLine(ex.ToString)
        End Try
    End Sub

    '---receiving a message from the client
    Public Sub ReceiveMessage(ByVal ar As IAsyncResult)
        '---read from client---
        Dim bytesRead As Integer
        Try
            SyncLock _client.GetStream
                bytesRead = _client.GetStream.EndRead(ar)
            End SyncLock
            '---client has disconnected
            If bytesRead < 1 Then
                AllClients.Remove(_clientIP)
                Broadcast("[UserDisconnected][" & _ClientNick & "]", Nothing)
                'Me.BroadCastUserList()
                Exit Sub
            Else
                '---receive the message sent
                Dim messageReceived As String = _
                  System.Text.Encoding.ASCII.GetString(data, 0, bytesRead)
             

Broadcast(messageReceived ,nothing)

            '---continue reading from client
            SyncLock _client.GetStream
                _client.GetStream.BeginRead(data, 0, _
                CInt(_client.ReceiveBufferSize), _
                AddressOf ReceiveMessage, Nothing)
            End SyncLock
        Catch ex As Exception
            AllClients.Remove(_clientIP)
            Broadcast("[UserDisconnected][" & _ClientNick & "]", Nothing)
           
        End Try
    End Sub

    Private Sub BroadCastUserList(ByVal users() As String)


        '===client is request for all users names===
        ' e.g. [Usrs]

        '---get all the users---
        Dim allUsers As String = "[UserList]["
        Dim c As DictionaryEntry
        For Each c In AllClients
            '---get all the users' name
            allUsers += _
              CType(c.Value, CommandClient)._ClientNick & "," & CType(c.Value, CommandClient)._ClientMachinename & "," & CType(c.Value, CommandClient)._clientIP & "," & CType(c.Value, CommandClient)._ClientTimestamp & "|"
        Next
        allUsers += "]"
        'e.g. [Usrs][User1,User2,etc]


        Broadcast(allUsers, users)

    End Sub

    '---broadcast message to selected users
    Public Sub Broadcast(ByVal message As String, ByVal users() As String)

        If users Is Nothing Then
            '---broadcasting to everyone
            Dim c As DictionaryEntry
            For Each c In AllClients
                '---broadcast message to all users
                CType(c.Value, CommandClient).SendMessage(message & vbCrLf)
            Next
            '---log it locally
            Console.WriteLine("---> " & Left(message, 100) & "...")

        Else
            '---broadcasting to selected ones

            Dim c As DictionaryEntry
            For Each c In AllClients
                Dim user As String

                For Each user In users
               
                    If CType(c.Value, CommandClient)._ClientNick = user Then
                        '---send message to user
                        CType(c.Value, CommandClient).SendMessage(message & vbCrLf)
                        '---log it locally
                        Console.WriteLine("---> " & Left(message, 100) & "...")

                        Exit For
                    End If
                Next
            Next

        End If
    End Sub
End Class

-----------------------------------------------------------

... også gerne hvordan jeg kan lave det om til en winapp istedet?
Avatar billede arne_v Ekspert
05. maj 2006 - 15:50 #1
jeg ville nok gemme clients i Main fremfor at lade dem registrere sig selv
i constructor (nemmere at gennemskue naar man laeser koden)

det ville naturligvis kraeve at brodcast metoderne blev flyttet til en
main class, men det ville vel ogsaa vaere paenene

jeg ville konsekvent bruge impport og korte klasse navne

jeg er ikke 100% sikker paa at
    SyncLock _client.GetStream
virker efter hensigten (hvis hvert kald af GetStream constuctor et object saa
virker det ikke)

GUI er nemt - i.s.f. Console.WriteLine appender du text til en win form control
Avatar billede agerled Nybegynder
05. maj 2006 - 15:56 #2
hej

1: Hvordan erstatter jeg Module1.vb i min win app?

2: Er dette det samme som multicasting eller er multicasting bedre?
Avatar billede agerled Nybegynder
05. maj 2006 - 16:00 #3
3: Er der noget fordel ved at køre det i en console app?
Avatar billede arne_v Ekspert
05. maj 2006 - 16:06 #4
re 2)

rigtig broadcast/multicast er paa lavere niveauer

du kan godt kalde det at sende til alle client for broadcast
Avatar billede arne_v Ekspert
05. maj 2006 - 16:08 #5
re 3)

en console app vil vaere nemmere at konvertere til en windows service
Avatar billede agerled Nybegynder
05. maj 2006 - 16:12 #6
OK. Kan du også klare spørgsmål 1: ?

Og for at det ikke skal være løgn kommer der også lige en nummer 4.

4: Jeg har nemlig også det problem at alle karaktererne  æ ø å bliver til "?" når der sendes tekst?
Avatar billede arne_v Ekspert
05. maj 2006 - 16:13 #7
re 1)

du kan ihvertfald altid aendre koden

jeg ved ikke hvordan man renamer i VS men jeg tror at man kan
Avatar billede agerled Nybegynder
05. maj 2006 - 16:16 #8
ang. 1: skal sub Main så ikke hede noget andet?
Avatar billede arne_v Ekspert
05. maj 2006 - 16:18 #9
re 4)

Encoding.ASCII -> Encoding.Default
Avatar billede arne_v Ekspert
05. maj 2006 - 16:23 #10
du kan bare andre koden fra Moduke til Class

Main hedder stadig Main, men du kan da putte en Public paa
Avatar billede agerled Nybegynder
05. maj 2006 - 16:33 #11
ok. jeg takker mange gang for din hjælp

...Men ellers synes du ikke der noget som kan gøres bedre / skal ændres i selve koden?

Læg bare et svar..
Avatar billede arne_v Ekspert
05. maj 2006 - 16:46 #12
det var ihvertfald det som lige sprang i oejnene

og svar
Avatar billede agerled Nybegynder
05. maj 2006 - 19:20 #13
Jeg kan ikke få den module1.vb til at virke i en winapp. Kan en eller anden vise mig hvordan?
Avatar billede arne_v Ekspert
05. maj 2006 - 20:18 #14
hvordan virker det ikke ?

du skal jo ihvertfald aabne din form ogsaa ...
Avatar billede agerled Nybegynder
05. maj 2006 - 22:24 #15
Hvordan skal nedenstående se ud i startformen?


Imports System.Net.Sockets

Module Module1
    Const portNo As Integer = 501
    Dim localAdd As System.Net.IPAddress = System.Net.IPAddress.Parse("10.11.10.50")
    'Dim localAdd As System.Net.IPAddress = System.Net.IPAddress.Parse("127.1.0.0")
    Dim listener As New System.Net.Sockets.TcpListener(localAdd, portNo)

    Sub Main()
        listener.Start()
        While True
            Dim user As New CommandClient(listener.AcceptTcpClient)
        End While
    End Sub
End Module
Avatar billede arne_v Ekspert
06. maj 2006 - 04:53 #16
måske noget a la:

    Sub ThreadLoop()
        listener.Start()
        While True
            Dim user As New CommandClient(listener.AcceptTcpClient)
        End While
    End Sub
    Sub Main()
          call (New Thread(AddressOf ThreadLoop)).Start
          Application.Run(New MainForm)
    End Sub
Avatar billede agerled Nybegynder
06. maj 2006 - 11:55 #17
ok, skal jeg så bare kalde sub main i min form_load?
Avatar billede arne_v Ekspert
07. maj 2006 - 03:03 #18
nej

men så


    Sub ThreadLoop()
        listener.Start()
        While True
            Dim user As New CommandClient(listener.AcceptTcpClient)
        End While
    End Sub

og

call (New Thread(AddressOf ThreadLoop)).Start

i din Form_load
Avatar billede agerled Nybegynder
08. maj 2006 - 06:30 #19
TAK.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester