Class tcp/ip listener tres simple et multithread dotnet

Soyez le premier à donner votre avis sur cette source.

Snippet vu 23 452 fois - Téléchargée 45 fois

Contenu du snippet

C'est un de mes premiers code dotnet, soyez indulgent :)
J'ai la fleme de poster le zip alors les plus motivés copie/colleront :p

Source / Exemple :


Imports System.Threading

Public Class clsListener

	Private intPort As Integer
	Private intMaxThreads As Integer
	Private intActiveThreads As Integer
	Private bListening As Boolean
	Private intTimeOut As Integer
	Private tcpListener As System.Net.Sockets.TcpListener
	Private WithEvents tmrListener As System.Windows.Forms.Timer

	Public Sub New()
		intPort = 6042		 'A redéfinir
		intTimeOut = 3000
		intMaxThreads = 2
		tmrListener = New Windows.Forms.Timer()
		tmrListener.Enabled = False
		tmrListener.Interval = 100
	End Sub

	Public Property Listening() As Boolean
		Get
			Return bListening
		End Get
		Set(ByVal Value As Boolean)
			Dim ret As Boolean
			If Not (bListening) Then
				ret = Start_Listening()
			Else
				ret = Stop_Listening()
			End If
			If ret Then
				bListening = Not (bListening)
			End If
		End Set
	End Property
	Public Property Port() As Integer
		Get
			Return intPort
		End Get
		Set(ByVal Value As Integer)
			intPort = Value
		End Set
	End Property
	Public Property maxThreads() As Integer
		Get
			Return intMaxThreads
		End Get
		Set(ByVal Value As Integer)
			If Value > 0 Then
				intMaxThreads = Value
			End If
		End Set
	End Property
	Public Property TimeOut() As Integer
		Get
			Return intTimeOut
		End Get
		Set(ByVal Value As Integer)
			If Value > 0 Then
				intTimeOut = Value
			End If
		End Set
	End Property
	Public ReadOnly Property CurrentThreads() As Integer
		Get
			Return intActiveThreads
		End Get
	End Property

	Public Event PostMessage(ByVal dTimePosted As Date, ByVal strHost As String, ByVal rawMessage As String)

	Private Function Start_Listening() As Boolean
		Try
			If Not tcpListener Is Nothing Then
				tcpListener.Stop()				   'Normalement inutile (dans un premier temps)
			Else
				tcpListener = New Net.Sockets.TcpListener(intPort)
			End If
			tcpListener.Start()
			tmrListener.Enabled = True
		Catch e As Exception
			Console.WriteLine(e.ToString)
			Return False
		End Try
		Return True
	End Function
	Private Function Stop_Listening() As Boolean
		Try
			If Not tcpListener Is Nothing Then
				tcpListener.Stop()
			End If
			tcpListener = Nothing
		Catch e As Exception
			Console.WriteLine(e.ToString)
			Return False
		End Try
		Return True
	End Function

	Private Sub GettingRawMessage(ByVal strHost As String, ByVal strMessage As String)
		RaiseEvent PostMessage(Now(), strHost, strMessage)
	End Sub

	Private Sub NewThread()
		intActiveThreads += 1
	End Sub
	Private Sub EndThread()
		intActiveThreads -= 1
	End Sub

	Private Sub tmrListener_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles tmrListener.Tick

		Dim CurThreadStart As Threading.ThreadStart
		Dim CurThread As Threading.Thread
		Dim ThreadCount As Integer
		Dim i As Integer

		If Not (tcpListener.Pending()) Or (intActiveThreads >= intMaxThreads) Then
			Exit Sub
		End If

		tmrListener.Enabled = False

		Dim Connfollow As New clsFollowConn()
		Connfollow.tcpListener = tcpListener
		Connfollow.TimeOut = 5000

		AddHandler Connfollow.post_message, AddressOf GettingRawMessage
		AddHandler Connfollow.connect, AddressOf NewThread
		AddHandler Connfollow.disconnect, AddressOf EndThread

		CurThreadStart = New Threading.ThreadStart(AddressOf Connfollow.AcceptConnection)
		CurThread = New Threading.Thread(CurThreadStart)
		CurThread.Start()

		tmrListener.Enabled = True

	End Sub

End Class
Public Class clsFollowConn

	Private Declare Function GetTickCount Lib "kernel32" () As Integer
	Private intLastDataTime As Integer
	Private intTimeOut As Integer
	Private Const EoM = vbCrLf
	Public tcpListener As Net.Sockets.TcpListener

	Public Event disconnect()
	Public Event connect()
	Public Event post_message(ByVal host As String, ByVal message As String)

	Public Sub AcceptConnection()

		Dim CurThread As System.Threading.Thread
		Dim CurSocket As Net.Sockets.Socket

		Dim Buffer(1024) As Byte
		Dim Bytes As Integer
		Dim strTemp As String
		Dim bStop As Boolean

		RaiseEvent connect()
		CurThread = System.Threading.Thread.CurrentThread()
		CurSocket = tcpListener.AcceptSocket

		intLastDataTime = GetTickCount()

		While Not (bStop)
			If CurSocket.Available > 0 Then
				Bytes = CurSocket.Receive(Buffer, Buffer.Length, 0)
				If Bytes > 0 Then
					strTemp += System.Text.Encoding.Default.GetString(Buffer, 0, Bytes)
					split_msg(CType(CurSocket.RemoteEndPoint, Net.IPEndPoint).Address.ToString(), strTemp)
					intLastDataTime = GetTickCount()
				End If
			End If
			Application.DoEvents()

			If Not (CurSocket.Connected) Or ((GetTickCount() - intLastDataTime) > intTimeOut) Then
				CurSocket.Close()
				bStop = True
			End If
		End While
		RaiseEvent disconnect()
	End Sub
	Private Sub split_msg(ByVal strHost As String, ByRef strData As String)
		Dim lngPosLf, lngPosLast As Integer
		lngPosLast = 1
		lngPosLf = InStr(strData, EoM)
		While lngPosLf > 0
			RaiseEvent post_message(strHost, Mid$(strData, lngPosLast, lngPosLf - lngPosLast))
			lngPosLast = lngPosLf + Len(EoM)
			lngPosLf = InStr(lngPosLast, strData, EoM)
		End While
		strData = Right(strData, Len(strData) + 1 - lngPosLast)
	End Sub

	Public ReadOnly Property LastDataTime() As Integer
		Get
			Return intLastDataTime
		End Get
	End Property
	Public Property TimeOut() As Integer
		Get
			Return intTimeOut
		End Get
		Set(ByVal Value As Integer)
			intTimeOut = Value
		End Set
	End Property

End Class

Conclusion :


Initialisation & Reception de "message" :

Private WithEvents myListener As clsListener

myListener = New clsListener()
myListener.Listening = True

Private Sub myListener_PostMessage(ByVal dTimePosted As Date, ByVal strHost As String, ByVal rawMessage As String) Handles myListener.PostMessage
MsgBox("Date : " & CStr(dTimePosted) & vbCrLf & "Host : " & strHost & vbCrLf & "Message : " & rawMessage)
End Sub

A voir également

Ajouter un commentaire

Commentaires

Bodekaer
Messages postés
3
Date d'inscription
lundi 9 décembre 2002
Statut
Membre
Dernière intervention
12 décembre 2002
-
Hi,

I am currently using your code in a VB.NET app I have created.

But when ever a thread is runinng, the loop that checks for new messages, uses a lot of CPU.
I actually thought that the Application.Doevents, would prevent the code from using a lot of CPU. But it doesn't.

I am sure it although wont affect the performance of other programs, but it looks "wild" the my program looks like it is using 100% of the CPU (and I am using a 2.5 Ghz machine :)

Is there anything to do to prevent this ?

/Michael
cs_zappy
Messages postés
161
Date d'inscription
mardi 19 juin 2001
Statut
Membre
Dernière intervention
10 avril 2007
-
Hi bodekaer,

I'm sorry, now i'm coding in C# and not in VB.NET.

You can use asynchronous sockets for betters performances without multi-threading (one thread / session is not good for a lot connections).

I have tested this code on my win2k : works with 5 connections without problem.

Happy coding !

ps: Sorry for my bad english :)
Bodekaer
Messages postés
3
Date d'inscription
lundi 9 décembre 2002
Statut
Membre
Dernière intervention
12 décembre 2002
-
No problem, my french isn't that good either :)

Well, I was wondering if you had a good example of hw to use asynchronous sockets in VB.NET

My program will normally handle between 30-90 connections at the same time.

/Michael
cs_zappy
Messages postés
161
Date d'inscription
mardi 19 juin 2001
Statut
Membre
Dernière intervention
10 avril 2007
-
I haven't that in VB.NET.

But i have a good link for C# programming sockets in a non-blocking mode.
http://www.codeproject.com/csharp/socketsincs.asp

Happy coding !
cs_RayBan
Messages postés
17
Date d'inscription
jeudi 24 janvier 2002
Statut
Membre
Dernière intervention
9 juin 2004
-
Hi,

I am not sure, but there a TCPListener class in .Net, that do all the thing your code do...

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.