我尝试开发一个多线程异步服务器套接字工具。我的工具基于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连接是一个问题吗?我的客户应该与服务器断开连接吗?