• 0
Sign in to follow this  
Lucas Phillip

Multiplas Conexões Tcp

Question

Olá :D

gente, eu estou aprendendo agora vb.net e estou tentando fazer um servidor que aceite multiplas conexões. Bom eu consegui fazer o servidor conectar a um cliente, mas não consegui de jeito nenhum fazer multiplos clientes conectarem.

Eu até dei uma pesquisada no forum e achei algumas referencias sobre esse assunto, mas como ainda estou aprendendo, elas geraram mais duvidas que soluções.

Aqui está o codigo que utilizei para conectar o cliente e o servidor...

Try
            Listener = New TcpListener(addr, port)

            Listener.Start()

            While True

                'aceita conexão e configura
                Connection = Listener.AcceptSocket()

                socketStream = New NetworkStream(Connection)

                StreamOut = New BinaryWriter(socketStream)
                StreamIn = New BinaryReader(socketStream)

                StreamOut.Write("Conexão Sucedida")

como faço para o servidor aceitar multiplas conexões e saber diferencia-las uma da outra?

vlw :D

Share this post


Link to post
Share on other sites

13 answers to this question

Recommended Posts

  • 0

Ao fazer...

Connection = Listener.AcceptSocket()

... você está aceitando a conexão e jogando a mesma para o objeto Connection. Se você fizer isso uma segunda vez, estará gerando *outra* conexão e assim por diante. Ou seja, cada objeto refere-se a uma conexão. Ou seja, fazendo um loop, você poderia aceitar múltiplas conexões. É interessante também usar o parâmetro backlog do método Start do seu objeto Listener para definir a quantidade de conexões pendentes (aguardando para serem aceitas).

Abraços,

Graymalkin

Share this post


Link to post
Share on other sites
  • 0

aí gray,

vlw pela resposta, mas ainda to com problema..

o servidor está ate aceitando multiplas conexões... mas como eu faço para pode comunicar com os clientes conectados. porque quando uma pessoa conecta, o servidor envia msg atraves do objeto streamout... só que quando uma outra conecta, as duas conexão param de receber as msg enviadas pelo streamout...

eu pensei então que talvez se eu fizesse um array com o streamout para cada conexão desse, mas também não funcionou não :(

Share this post


Link to post
Share on other sites
  • 0

Você está realmente utilizando objetos diferentes ou você está reaproveitando o mesmo objeto? Porque se for o segundo o caso, você vai estar perdendo a conexão anterior. E sim, a idéia é justamente usar uma estrutura de lista (como uma ArrayList) para guardar as conexões a fim de que depois você possa se comunicar com os clientes.

Abraços,

Graymalkin

Share this post


Link to post
Share on other sites
  • 0

aew,

bom, o objeto para enviar já esta em um array e funciona.. o problema é para receber...

tava assim

            Do
                IncomeMessage = StreamIn.ReadString()

                Explode = Split(IncomeMessage, "|")

                Select Case (Explode(0))
                    Case "chat"

                        For X = 1 To (iUsers - 1)

                            StreamOut(X).Write(IncomeMessage)
                            StreamOut(X).Flush()

                        Next

                End Select

            Loop While True
ai desse jeito, enquanto apenas 1 usuario estivesse enviando, estava tudo bem, mas quando um outro enviava uma mensagem também, então a conexão era perdida. ai você falo pra coloca num array, e fiz isso, mas do jeito que eu fiz só "quase" funcionou... coloquei o "streamin" num array também, e para receber substitui
IncomeMessage = StreamIn.ReadString()
por
for y = 1 to (iusers -1)
IncomeMessage = StreamIn(y).ReadString()
next

bom, desse jeito, as vezes funcionava, as vezes não.. tinha mensagens que não chagavam, ai quando mandava uma outra, era a antiga que chegava...

bom, se não da pra usar o for pra verificar cada campo do array, como eu faço para verificar se um cliente mandou uma msg?

vlw :D

Share this post


Link to post
Share on other sites
  • 0

No caso, uma das maneiras seria iniciar vários processos (threads), sendo um para cada cliente e no qual haveria o loop para o recebimento dos dados. Eu comecei a escrever um P2P (peer-to-peer, tipo eMule, KaZaA, etc.), em VB2005, no qual utilizei justamente essa técnica.

Abraços,

Graymalkin

Share this post


Link to post
Share on other sites
  • 0

bom, to quase lá :D

eu tentei fazer o que você falou, mas surgiu um ultimo problema (pelo menos espero que seja)... eu criei uma thread para cada usuario que conectar.

só que na hora de receber, eu criei uma variavel que a cada thread vai aumentando em 1, para ir acompanhando as novas threads e ser o "numero" do usuario para receber... o problema é que quando eu aumento essa variavel, aumenta ela em todas as threads e acaba dando na mesma :P

como eu faço então pra fazer uma variavel, num array de threads, que vai aumentando, mas não aumenta em todas as threads, só na que ele foi "aumentado"?

vlw :D

Share this post


Link to post
Share on other sites
  • 0

Você pode declará-la como estática (Static) a fim de que seu valor seja lembrado para aquela rotina específica. Ou melhor ainda, crie uma classe representando o usuário conectado (ao qual você pode atribuir um número, se quiser).

Abraços,

Graymalkin

Share this post


Link to post
Share on other sites
  • 0

Aew,

bom, com a ajuda do Graymalking, eu consegui resolver meu problema de multiplas conexoes e ficou otimo... só ficou um problema... toda vez que uma pessoa nova conecta cria um usuario novo ela ao invés de reutilizar uma conexão livre, ela cria uma nova... ai o nº total de usuarios só vai aumentando infinitamente...

ai eu fiz um codigo que procura pelo numero de uma conexão fechada e utiliza ela para a proxima conexão... o problema é que não estou conseguindo passar esse numero para dentro das threads das conexões... antes eu tinha feito como o gray falou, declarei ela static e tava funcionando.. mas só estava funcionando porque como a cada conexao nova, simplesmente aumentava o valor de conexões +1, era só aumentar +1 ao "numero da conexao"... agora esse numero pode variar e como já disse, não to conseguindo pegar ele...

bom, vo posta aqui como tentei...

codigo para receber conexoes

 While True

                'aceita conexão e configura
                Connection(SocketLivre) = Listener.AcceptSocket()

                socketStream(SocketLivre) = New NetworkStream(Connection(SocketLivre))

                StreamOut(SocketLivre) = New BinaryWriter(socketStream(SocketLivre))
                StreamIn(SocketLivre) = New BinaryReader(socketStream(SocketLivre))

                SetText(iUsers)

                'inicia threads para comunicação
                ConThread(SocketLivre) = New Thread(AddressOf PlayersIO)
                ConThread(SocketLivre).Start()

                Dim AchouLivre As Boolean = False

                'acha socket livre
                If (iUsers > 1) Then

                    For Z = 1 To iUsers

                        Try

                            If (Connection(Z).Connected = False) Then

                                SocketLivre = Z
                                AchouLivre = True
                                Exit For

                            End If

                        Catch Null As NullReferenceException

                            'não faz nada...

                        End Try

                    Next

                End If

                'se não achar, adiciona novo usuario
                If (AchouLivre = False) Then

                    iUsers += 1
                    SocketLivre = iUsers

                End If

            End While
codigo das threads
 Public Sub PlayersIO()

(...)
        Dim InnerThread As Short

        InnerThread = SocketLivre - 1

(...)
End Sub

alguém sabe me ajuda?? vlw :D

Share this post


Link to post
Share on other sites
  • 0

Você não deveria procurar o socket livre *antes* de aceitar a conexão (para poder justamente usá-lo para tal fim)?

Abraços,

Graymalkin

Share this post


Link to post
Share on other sites
  • 0

com certeza... mas o que eu reparei era o seguinte: no loop para aceitar conexões, se eu colocava uma msgbox antes da linha "Connection(SocketLivre) = Listener.AcceptSocket()" a msg aparecia na hora de carregar o programa.. se eu colocava depois, a msg só aparecia na hora que recebia uma conexão..

então eu conclui que no loop, ao chegar em "Connection(SocketLivre) = Listener.AcceptSocket()", ele parava o loop e ficava esperando ate receber uma conexão para continuar...

ai acabo que deu na mesma se eu coloco para procurar antes ou depois, porque mesmo eu colocando antes, depois que receber a 1 conexão, ele já vai preparar a 2 segunda conexão como não tendo ninguém... eu só coloquei pra procurar a conexao depois de aceitar porque tava fazendo testes e fico assim minha ultima tentativa (que o resultado deu exatamente o mesmo quando coloquei pra procurar antes)

deu pra entender? :D

Share this post


Link to post
Share on other sites
  • 0

Entendi mais ou menos. Sendo que num contexto de múltiplas conexões, existe diferença entre procurar antes ou depois de aceitar a conexão.

Abraços,

Graymalkin

Share this post


Link to post
Share on other sites
  • 0

aew... bom, acho que to quase la :blink:

agora eu só não to sabendo fechar as conexões para que elas sejam reutilizadas por outros usuarios..

está assim:

 Dim AchouLivre As Boolean = False

                'acha socket livre
                If (iUsers > 1) Then

                    For Z = 1 To iUsers

                        Try

                            If (Connection(Z).Connected = False) Then

                                SocketLivre = CShort(Z)
                                AchouLivre = True
                                Exit For

                            End If

                        Catch Null As NullReferenceException

                            'não faz nada...

                        End Try

                    Next

                End If

                'se não achar, adiciona novo usuario
                If (AchouLivre = False) Then

                    iUsers = CShort(iUsers + 1)
                    SocketLivre = iUsers

                End If

                'aceita conexão e configura
                Connection(SocketLivre) = Listener.AcceptSocket()

                socketStream(SocketLivre) = New NetworkStream(Connection(SocketLivre))

                StreamOut(SocketLivre) = New BinaryWriter(socketStream(SocketLivre))
                StreamIn(SocketLivre) = New BinaryReader(socketStream(SocketLivre))

                'inicia threads para comunicação
                ConThread(SocketLivre) = New Thread(AddressOf PlayersIO)
                ConThread(SocketLivre).Start(SocketLivre)
e para fechar a conexão
        Connection(QualThread).Close()
        socketStream(QualThread).Close()

        StreamOut(QualThread).Close()
        StreamIn(QualThread).Close()

        ConThread(QualThread).Abort()

eu na verdade não tinha muito ideia de como fazer para fechar as conexões então tentei desse jeito ai em cima.. mas assim não funciona.. qual o jeito correto de fazer isso?

vlw

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this