Socket server won't accept connections

Mirace

Member
Joined
Apr 29, 2012
Messages
9
Programming Experience
3-5
Hello, i can't see why this code is not working.

VB.NET:
Option Strict On

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


Public Class Form1


    'Form Controls.
    Private lblListenPort As New Label
    Private txtListenPort As New TextBox
    Private WithEvents btnStartStop As New Button
    Private lvwMessages As New ListView


    'Global Objects.
    Private gListeningSocket As Socket = Nothing
    Private gPort As Integer = 0
    Private gListening As Boolean = False
    Private gStopListening As Boolean = False
    Private gConnectionIndex As Integer = -1


    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load


        'Setup form controls.
        With Me
            .Text = "Message Server"
            .Size = New System.Drawing.Size(900, 600)
            .Controls.Add(lvwMessages)
            .Controls.Add(btnStartStop)
            .Controls.Add(txtListenPort)
            .Controls.Add(lblListenPort)
        End With
        With lblListenPort
            .Text = "Listen Port:"
            .Dock = DockStyle.Top
        End With
        With txtListenPort
            .Text = "20912" 'Random port.
            .Dock = DockStyle.Top
        End With
        With btnStartStop
            .Text = "Start Listening"
            .Dock = DockStyle.Top
        End With
        With lvwMessages
            .Dock = DockStyle.Fill
            .View = View.Details
            .GridLines = True
            .FullRowSelect = True
            .MultiSelect = False
            .Scrollable = True
            .Columns.Add("Direction") 'Text
            .Columns.Add("Conn ID") 'SubItem 1
            .Columns.Add("Client IP") 'SubItem 2
            .Columns.Add("Dec") 'SubItem 3
            .Columns.Add("Hex") 'SubItem 4
            .Columns.Add("Chr") 'SubItem 5
            For Each vCol As ColumnHeader In .Columns
                vCol.Width = CInt(Math.Floor(.Width / .Columns.Count)) - CInt(Math.Floor(30 / .Columns.Count))
            Next
        End With
    End Sub


    Private Sub btnStartStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStartStop.Click


        'Is the socket already listening?
        If gListening Then
            StopListening()
            Exit Sub
        Else
            gPort = 7112 'CInt(txtListenPort.Text)
            If gPort <= 0 Then MessageBox.Show("Invalid port.  Please specify the port.") : Exit Sub
        End If


        'See if specified port is already being used.  If not, bind to it.
        Try
            Dim vEndPoint As New IPEndPoint(IPAddress.Any, gPort)
            gListeningSocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
            gListeningSocket.Bind(vEndPoint)
            Dim vBacklog As Integer = 1000
            gListeningSocket.Listen(vBacklog)
            gListening = True
            gStopListening = False
            btnStartStop.Text = "Stop Listening"
        Catch ex As Exception
            MessageBox.Show("Bad port specified, or port already in use.")
            Exit Sub
        End Try


        'Start listening.
        Dim vThread As New Thread(AddressOf ListenBackground)
        With vThread
            .IsBackground = True
            .Name = "Listener thread for port " & gPort
        End With
        vThread.Start()
    End Sub


    Private Sub ListenBackground()


        'Listen in a loop until cancelled...
        Do Until gStopListening


            'The loop will wait until a client makes a connection attempt.
            Dim vCommunicationSocket As Socket = gListeningSocket.Accept()


            'If an attempt is made, accept it in the form of a new socket with which to receive/send data from/to this client.
            If vCommunicationSocket.Connected = True Then


                'Even though we have made a connection to a client, we're not going quit listening for further connections
                'from other clients (or maybe the same client at a later date).  So we will give this connection an ID so it can
                'be distinguished from other connections.  We do this by incrementing a counter.  Its ID will be the value of
                'the counter.
                gConnectionIndex += 1


                'The client has accepted, now spawn a thread to wait for data from the client.
                Dim vThread As New Thread(AddressOf ReceiveBackground)
                With vThread
                    .IsBackground = True
                    .Name = "Receiver thread for connection " & gConnectionIndex & " on port " & gPort
                End With


                'A single object can be passed into the thread via the Start() method's optional parameter.
                'Since we need both the connection ID and the socket itself, we will pass an object that contains both.
                Dim vSocketAndId As New SocketAndId
                With vSocketAndId
                    .ConnectionId = gConnectionIndex
                    .ConnectionSocket = vCommunicationSocket
                End With
                vThread.Start(CType(vSocketAndId, Object))
            End If


            'Continue listening for new connections...
        Loop


        'Stop listening.
        gListeningSocket.Close()
        gListening = False
        ReportDoneListening_CrossThread()
    End Sub


    Private Sub ReceiveBackground(ByVal Args As Object)
        Dim vConnectionId As Integer = CType(Args, SocketAndId).ConnectionId
        Dim vConnectionSocket As Socket = CType(Args, SocketAndId).ConnectionSocket


        'Timeout will be 0.5 seconds.
        Dim vTimeout As Integer = 500
        vConnectionSocket.ReceiveTimeout = vTimeout


        'For our little example, we expect all messages to be 1024 bytes or below (arbitrary amount).
        Dim vMessageLength As Integer = 1024


        'Remember, when dimensioning arrays, the integer specified is the upper bounds, not the length.
        Dim vClientMessage(vMessageLength - 1) As Byte


        'Receive.
        Dim vNumOfBytesReceived As Integer = 0
        Try
            vNumOfBytesReceived = vConnectionSocket.Receive(vClientMessage, 0, vMessageLength, SocketFlags.None)
        Catch ex As Exception
            If vConnectionSocket.Connected Then vConnectionSocket.Close()
            'MessageBox.Show(String.Format("Timeout occurred before receiving any bytes.  Connection with client {0} closed.", vConnectionId))
            Exit Sub
        End Try


        'Did we receive any bytes from the client?
        If (vNumOfBytesReceived < 1) OrElse (vConnectionSocket.Connected = False) Then
            If vConnectionSocket.Connected Then vConnectionSocket.Close()
            'MessageBox.Show(String.Format("Did not receive any bytes.  Connection with client {0} closed.", vConnectionId))
            Exit Sub
        End If


        'Trim empty bytes from array.
        Dim vTrimmedClientMessage(vNumOfBytesReceived - 1) As Byte
        Array.Copy(vClientMessage, vTrimmedClientMessage, vNumOfBytesReceived)


        'Return bytes.
        Dim vReceivedData As New SentOrReceivedData
        With vReceivedData
            .ConnectionId = vConnectionId
            .RemoteIp = vConnectionSocket.RemoteEndPoint.ToString
            .NumOfBytes = vNumOfBytesReceived
            .ActualBytes = vTrimmedClientMessage
        End With
        ReportDoneReceiving_CrossThread(CType(vReceivedData, Object))


        'Prepare response message to client.
        Dim vResponseMessage As Byte() = Encoding.UTF8.GetBytes("Message Received!")


        'Send response.
        Try
            vConnectionSocket.Send(vResponseMessage)


            'Return bytes.
            Dim vSentData As New SentOrReceivedData
            With vSentData
                .ConnectionId = vConnectionId
                .RemoteIp = vConnectionSocket.RemoteEndPoint.ToString
                .NumOfBytes = vResponseMessage.Length
                .ActualBytes = vResponseMessage
            End With
            ReportDoneSending_CrossThread(CType(vSentData, Object))
        Catch ex As Exception


            'Report fail or timeout.
            If vConnectionSocket.Connected Then vConnectionSocket.Close()
            'MessageBox.Show(String.Format("Could not send bytes.  Connection with client {0} closed.", vConnectionId))
            Exit Sub
        End Try
    End Sub


    Private Sub StopListening()


        'We set the stop signal to true so that the listener does not enter another iteration of the loop.
        gStopListening = True


        'However, since the .NET framework doesn't have any sort of "timeout" property for any of the
        'accept methods (e.g. Accept(), BeginAccept(), EndAccept(), etc), the loop will never exit the
        'current iteration because it is still waiting on the Accept() line for a connection.  So we will
        'have to give it what it wants; we will have to send our own connection just so it can accept
        'something and break out of the deadlock.


        Try
            Dim vIp As IPAddress = IPAddress.Parse("127.0.0.1") 'Loop-back IP address (localhost).
            Dim vEndPoint As New IPEndPoint(vIp, gPort)
            Using vSocket As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
                vSocket.Connect(vEndPoint)


                'Because we're using a "Using" block, the socket will dispose itself after sending.  Part
                'of its disposal process is to shut down the socket connection (so we don't have to
                'manually tell it to disconnect).  This is good b/c the listener will receive TCP
                'handshake disconnect info that tells it that the connection has ended, and it will then
                'close its side of the socket immediatly, rather than waiting for the Receive() method to
                'time out.
            End Using
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
    End Sub


    Private Sub ReportDoneListening_CrossThread()
        If Me.InvokeRequired Then
            Me.Invoke(New ReportDoneListening_Delegate(AddressOf ReportDoneListening))
        Else
            ReportDoneListening()
        End If
    End Sub
    Private Delegate Sub ReportDoneListening_Delegate()
    Private Sub ReportDoneListening()
        btnStartStop.Text = "Start Listening"
    End Sub


    Private Sub ReportDoneReceiving_CrossThread(ByVal pArg As Object)
        If Me.InvokeRequired Then
            Me.Invoke(New ReportDoneReceiving_Delegate(AddressOf ReportDoneReceiving), pArg)
        Else
            ReportDoneReceiving(pArg)
        End If
    End Sub
    Private Delegate Sub ReportDoneReceiving_Delegate(ByVal pArg As Object)
    Private Sub ReportDoneReceiving(ByVal pArg As Object)
        Dim vConnectionId As Integer = CType(pArg, SentOrReceivedData).ConnectionId
        Dim vRemoteIp As String = CType(pArg, SentOrReceivedData).RemoteIp
        Dim vNumOfBytesReceived As Integer = CType(pArg, SentOrReceivedData).NumOfBytes
        Dim vReceivedBytes As Byte() = CType(pArg, SentOrReceivedData).ActualBytes


        For Each vByte As Byte In vReceivedBytes
            Dim vLvi As New ListViewItem
            With vLvi


                'Direction column.
                .Text = "RECV -->"


                'Connection ID column.
                .SubItems.Add(CStr(vConnectionId))


                'Client IP column.
                .SubItems.Add(vRemoteIp)


                'Decimal column.
                .SubItems.Add(vByte.ToString)


                'Hexidecimal column.
                .SubItems.Add(vByte.ToString("X2"))


                'Character column.
                .SubItems.Add(ChrW(vByte))
            End With
            With lvwMessages
                .Items.Add(vLvi)
                .EnsureVisible(.Items.Count - 1)
            End With
        Next
    End Sub


    Private Sub ReportDoneSending_CrossThread(ByVal pArg As Object)
        If Me.InvokeRequired Then
            Me.Invoke(New ReportDoneSending_Delegate(AddressOf ReportDoneSending), pArg)
        Else
            ReportDoneSending(pArg)
        End If
    End Sub
    Private Delegate Sub ReportDoneSending_Delegate(ByVal pArg As Object)
    Private Sub ReportDoneSending(ByVal pArg As Object)
        Dim vConnectionId As Integer = CType(pArg, SentOrReceivedData).ConnectionId
        Dim vRemoteIp As String = CType(pArg, SentOrReceivedData).RemoteIp
        Dim vNumOfBytesSent As Integer = CType(pArg, SentOrReceivedData).NumOfBytes
        Dim vSentBytes As Byte() = CType(pArg, SentOrReceivedData).ActualBytes


        For Each vByte As Byte In vSentBytes
            Dim vLvi As New ListViewItem
            With vLvi


                'Direction column.
                .Text = "<-- SENT"


                'Connection ID column.
                .SubItems.Add(CStr(vConnectionId))


                'Client IP column.
                .SubItems.Add(vRemoteIp)


                'Decimal column.
                .SubItems.Add(vByte.ToString)


                'Hexidecimal column.
                .SubItems.Add(vByte.ToString("X2"))


                'Character column.
                .SubItems.Add(ChrW(vByte))
            End With
            With lvwMessages
                .Items.Add(vLvi)
                .EnsureVisible(.Items.Count - 1)
            End With
        Next
    End Sub
End Class


Public Structure SocketAndId
    Public ConnectionId As Integer
    Public ConnectionSocket As Socket
End Structure


Public Structure SentOrReceivedData
    Public ConnectionId As Integer
    Public RemoteIp As String
    Public NumOfBytes As Integer
    Public ActualBytes As Byte()
End Structure
 
Instead of expecting us to trawl through all that code on the off chance that we might see something, how about you explain to use exactly what you expect to happen, what actually does happen and where in the code reality deviates from expectation? That way we can hone in on that and work out from there so and we don't waste our time on the irrelevant stuff?
 
Back
Top