多线程异步服务器套接字示例

时间:2015-02-01 10:49:16

标签: vb.net multithreading sockets asynchronous tcp

我尝试开发一个多线程异步服务器套接字工具。我的工具基于MSDN的样本(Link is here

我想将此代码用作多线程来侦听不同的端口。我会听近10个端口。这是我的代码我做了什么:

Imports System
Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports System.Threading
Imports Microsoft.VisualBasic
Public Class Form1
    ' Thread signal.
    Public Shared _clients As New List(Of Socket)()
    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. 
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        'ListenConnections(8081)
        Dim Listen = New Thread(Sub() ListenConnections(8081))
        Listen.Start()
        Dim Listen2 = New Thread(Sub() ListenConnections(8080))
        Listen2.Start()
    End Sub
    Public Shared Sub ListenConnections(ByVal Port As Integer)
        Dim bytes() As Byte = New [Byte](1023) {}

        ' Establish the local endpoint for the socket.
        Dim ipHostInfo As IPHostEntry = Dns.GetHostEntry(Dns.GetHostName())
        Dim ipAddress As System.Net.IPAddress = System.Net.IPAddress.Any
        Dim localEndPoint As New IPEndPoint(ipAddress, Port)

        ' 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
    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)
        _clients.Add(handler)
        ' 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)
        listener.BeginAccept(New AsyncCallback(AddressOf AcceptCallback), listener)
    End Sub 'AcceptCallback
    Public Shared Sub ReadCallback(ByVal ar As IAsyncResult)

        While True
            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
            Monitor.Enter(handler)
            ' 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))
                content = 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("|") > -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
                allDone.Set()
            Else
                handler.Shutdown(SocketShutdown.Both)
                handler.Close()
                handler = Nothing
                handler = state.workSocket
            End If
        End While
        Monitor.Exit(ar)
    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

我在ReadCallback sub上遇到了这个错误:

" 每次异步操作只能调用一次EndReceive "

(在这一行:Dim bytesRead As Integer = handler.EndReceive(ar))

我该如何纠正这个问题?你对我的代码有什么建议吗?该服务器将工作7/24。作为最后一个问题,我的客户端将连接到此服务器一次,可能是他们不会断开1个月(实际上除非没有任何问题,否则他们不应该断开连接)。长时间TCP连接是一个问题吗?我的客户应该与服务器断开连接吗?

0 个答案:

没有答案