can you provide me with the old source plz? i would like to see the difference.
thankyou before.
I don't actually have the old code anymore, but I can certainly recreate it without too much trouble. When I get a chance today, I'll re-implement one of the classes that currently uses a SynchronizationContext and give it a SynchronisingObject property.
can you provide me with the old source plz? i would like to see the difference.
thankyou before.
It took a little longer to get around to it than I planned but I've redone the project so that the MessageClient and MessageServer classes now use a SynchronisingObject property. Do a "Find in Files" on that and you'll find all the changes.
I keep getting "Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host." aswell .. me on line "Dim byteCount = stream.EndRead(ar)" of MessageServer.Read - it's in a try catch and still throws the error
Um... how am i supposed to uniquely identify a user ...
Just say I have a LAN of 100 people accessing a remote server across the net - to the server they all will have the same IP address and the MessageReceived etc events just pass around the HostInfo structure that only contains the IP and port but nothing to uniquely identify each connection.
Data = System.Text.Encoding.ASCII.GetString(System.Text.Encoding.Unicode.GetBytes(e.message))
to convert the MessageReceived Response to ascii... but if the data is split across one send on the client (sent in vb script with windsock) the Data has some rubbish chrs at the end and the first received message and the 2nd received message has some rubbish chrs at the begining of data.
Is it possible to talk more natively in ascii rather than having to convert from unicode?
Data = System.Text.Encoding.ASCII.GetString(System.Text.Encoding.Unicode.GetBytes(e.message))
to convert the MessageReceived Response to ascii... but if the data is split across one send on the client (sent in vb script with windsock) the Data has some rubbish chrs at the end and the first received message and the 2nd received message has some rubbish chrs at the begining of data.
Is it possible to talk more natively in ascii rather than having to convert from unicode?
Thanks
Kris
If you want to pass the data as ASCII then just call ASCII.GetBytes when sending and ASCII.GetString when receiving. Once you convert a String to binary though, you MUST convert that binary back to a String using the same encoding. Think about it. Binary data is just numbers. It's how you interpret those numbers that gives them meaning. If you have a set of numbers that represents some Unicode text, how can you convert it to text using ASCII and expect to get a sensible result?
By the way, I didn't in my code but you can use a StreamWriter to write to the NetworkStream at one end and a StreamReader to read the NetworkStream at the other. You simply provide the Stream and the Encoding when you create them and then use them in the same way as you would to read or write a file.
If you want to pass the data as ASCII then just call ASCII.GetBytes when sending and ASCII.GetString when receiving. Once you convert a String to binary though, you MUST convert that binary back to a String using the same encoding. Think about it. Binary data is just numbers. It's how you interpret those numbers that gives them meaning. If you have a set of numbers that represents some Unicode text, how can you convert it to text using ASCII and expect to get a sensible result?
I am using ascii.getstring when receiving ... and it is putting the junk there
and the data was sent in ascii with the clients ... the clients use winsock in a vb script btw...
If the client sent the data as ASCII then you can read it as ASCII. If there's junk in the data then it was put there by the client. They must be adding some sort of header and/or footer to the data. If you can send ASCII data using a TcpClient and read it correctly using your server then you know it's not the server that's the issue. You need to determine what that header/footer is so that you can parse it and remove it from the data.
Just had another error on the same line this one reads: "Unable to read data from the transport connection: EndReceive can only be called once for each asynchronous operation.."
This is the stack trace for "Unable to read data from the transport connection: EndReceive can only be called once for each asynchronous operation.." that occurs on the line "Dim byteCount = stream.EndRead(ar)"
Code:
at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
at Wunnell.Net.MessageServer.Read(IAsyncResult ar) in C:\SARAH Registration Server\SARAH Registration Server\Wunnell.Net.MessageClientServer\MessageServer.vb:line 452
at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
at System.Net.ContextAwareResult.CompleteCallback(Object state)
at System.Threading.ExecutionContext.runTryCode(Object userData)
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Net.ContextAwareResult.Complete(IntPtr userToken)
at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
at System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
The call stack for the "forcibly closed" error is:
Code:
at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
at Wunnell.Net.MessageServer.Read(IAsyncResult ar) in C:\SARAH Registration Server\SARAH Registration Server\Wunnell.Net.MessageClientServer\MessageServer.vb:line 452
at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
at System.Net.ContextAwareResult.CompleteCallback(Object state)
at System.Threading.ExecutionContext.runTryCode(Object userData)
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Net.ContextAwareResult.Complete(IntPtr userToken)
at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
at System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
I just thought that I mention that I'm not ignoring these posts. I just don't know the solution because I have never encountered these errors and I don;t have the time for extensive testing right now. You might do better to post in the VB.NET forum about this specific problem and link back to this thread. Someone may have solved a similar issue who would not ever see your question in this thread.
Also get another error occasionally - does not take me to a line though ...
Error is: "Exception has been thrown by the target of an invocation."
This is the call stack:
Code:
at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)\r\n
at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)\r\n
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)\r\n
at System.Delegate.DynamicInvokeImpl(Object[] args)\r\n
at System.Windows.Forms.Control.InvokeMarshaledCallbackDo(ThreadMethodEntry tme)\r\n
at System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj)\r\n
at System.Threading.ExecutionContext.runTryCode(Object userData)\r\n
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)\r\n
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)\r\n
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)\r\n
at System.Windows.Forms.Control.InvokeMarshaledCallback(ThreadMethodEntry tme)\r\n
at System.Windows.Forms.Control.InvokeMarshaledCallbacks()\r\n
at System.Windows.Forms.Control.WndProc(Message& m)\r\n
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)\r\n
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)\r\n
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)\r\n
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)\r\n
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)\r\n
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)\r\n
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)\r\n
at System.Windows.Forms.Application.Run(ApplicationContext context)\r\n
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()\r\n
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()\r\n
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)\r\n
at SARAH_Registration_Server.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81\r\n
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)\r\n
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)\r\n
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()\r\n
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)\r\n
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)\r\n
at System.Threading.ThreadHelper.ThreadStart()
Also get another error occasionally - does not take me to a line though ...
Error is: "Exception has been thrown by the target of an invocation."
That error message occurs on the original thread when an exception occurs on a secondary thread. It's a safe bet that the original exception is being thrown in one of the callbacks. Is there an inner exception? There should be and that should contain the original exception.
Also thank you from Denmark .
This piece of code is simple, well-commented and very easy to expand upon.
I'm using a rewritten version of the code (allowing encryption, signatures and more complex data-transmission) with great success as an integrated part of a larger solution. There are occasional minor problems, that probably ties to the rewrites, but I'll mention one here anyways, since the solution may be helpful:
* Loss of net on either side caused an unhandled exception, that had to be handled in an application-event (NetworkAvailabilityChanged).
Regards and thanks again
Tom
In truth, a mature man who uses hair-oil, unless medicinally , that man has probably got a quoggy spot in him somewhere. As a general rule, he can't amount to much in his totality. (Melville: Moby Dick)
I am using this to talk between a vb6 winsock control
and all seems to be working well except for one thing...
I can receive data with no problems from the .net server, but when i send it i get no errors... the vb6 app just never receives the data - never had a problem before with the vb6 server that i used to use.
I am using this to talk between a vb6 winsock control
and all seems to be working well except for one thing...
I can receive data with no problems from the .net server, but when i send it i get no errors... the vb6 app just never receives the data - never had a problem before with the vb6 server that i used to use.
Great stuff all working well as an app ... just when i make it a service i get the following error:
Code:
System.NullReferenceException was unhandled
Message="Object reference not set to an instance of an object."
Source="Wunnell.Net.MessageClientServer"
StackTrace:
at Wunnell.Net.MessageClientServerBase.OnConnectionAccepted(ConnectionEventArgs e)
at Wunnell.Net.MessageServer.AcceptTcpClient(IAsyncResult ar)
at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
at System.Net.ContextAwareResult.CompleteCallback(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Net.ContextAwareResult.Complete(IntPtr userToken)
at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
at System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
InnerException:
(No inner exception)
I made a test app that does the following (only one user connects to the test app so didnt bother having a message buffer for each user):
The test app throws the same error...
The test app consists of:
vb Code:
Public Class Service1
Private WithEvents server As Wunnell.Net.MessageServer
Protected Overrides Sub OnStart(ByVal args() As String)
server = New Wunnell.Net.MessageServer(8016)
End Sub
Protected Overrides Sub OnStop()
server.Dispose()
End Sub
Dim message As String
Private Sub server_MessageReceived(ByVal sender As Object, ByVal e As Wunnell.Net.MessageReceivedEventArgs) Handles server.MessageReceived
The exception is telling you that there's a NullReferenceException in MessageClientServerBase.OnConnectionAccepted. What line is it thrown on and what reference on that line is Nothing?
The exception is telling you that there's a NullReferenceException in MessageClientServerBase.OnConnectionAccepted. What line is it thrown on and what reference on that line is Nothing?
Fixed as mentioned above ... and it was this throwing it:
vb Code:
Protected Overridable Sub OnConnectionAccepted(ByVal e As ConnectionEventArgs)
That's because the SynchronizationContext class only works in WinForms and WPF applications. It's purpose is to marshal a method call to the UI thread. There's no UI in a Windows service so there's no UI. There's no need to marshal method calls to a specific thread to updated controls so the SynchronizationContext class is not relevant.
Lovely work! Congratulations. I have to admit you saved me some billions years to make a lib like this hehehe.
I have one doubt. I observed you used Dim buffer As Byte() = Me.Encoding.GetBytes(message), in Send methods, to send data. I can remove this, and send data in ascii instead? is safe to do this? why do you use encoding? (just a curiosity)
Ready, im figured out how to transmit and receive in ASCII. Just replaced Me.Encoding.GetString with Me.Encoding.ASCII.GetString in server and client classes, rebuilded de DLL, and voila!
Sorry for disturbing you in programmer's olympus! hehehehe
Ready, im figured out how to transmit and receive in ASCII. Just replaced Me.Encoding.GetString with Me.Encoding.ASCII.GetString in server and client classes, rebuilded de DLL, and voila!
Sorry for disturbing you in programmer's olympus! hehehehe
That may get the job done but it's not the right way to do it. If you want to convert text to binary or vice versa then you need to use an Encoding object. ASCII is just an Encoding object that encodes in ASCII. If you wanted to use ASCII then you should have done one of two things:
1. Assigned System.Text.Encoding.ASCII to the Encoding property and used the code as is.
2. Got rid of the Encoding property and just used System.Text.Encoding.ASCII.GetBytes and .GetString instead.
Efectively, im replaced the line Me.Encoding.ASCII.GetString (that line give me a warning) with System.Text.Encoding.ASCII.GetString and all is working as suposed to do. Many thanks, and congratulations for your cool project.
Hi, im back again with a little question
Im added a dictionary (string, date) to project, everytime clients transmit data (key are host: port, value are hour), updates the dictionary with the last hour of transmition. A timer see every 30 seconds the dictionary, if any value are greater than 60 minutes, it remove from combobox and dictionary, but... how i can remove from hosts list and how close the port used? i see in MessageServer class a private sub called RemoveClient. Its possible to invoke that sub to close the port inside my app? or another mechanism to close a port and remove from hosts list?(i am making this 'cos sometimes clients disconnects and server keep port open, in this way i close the unused ports). Thanks again!
Hi, im back again with a little question
Im added a dictionary (string, date) to project, everytime clients transmit data (key are host: port, value are hour), updates the dictionary with the last hour of transmition. A timer see every 30 seconds the dictionary, if any value are greater than 60 minutes, it remove from combobox and dictionary, but... how i can remove from hosts list and how close the port used? i see in MessageServer class a private sub called RemoveClient. Its possible to invoke that sub to close the port inside my app? or another mechanism to close a port and remove from hosts list?(i am making this 'cos sometimes clients disconnects and server keep port open, in this way i close the unused ports). Thanks again!
You are only using one port at the server end. If you want to close a client connection then call Close on the TcpClient.
Sorry for disturbing you... how can call TcpClient close from inside server app? i have some minutes trying but nothing, my level of expertise are very low.
Sorry for disturbing you... how can call TcpClient close from inside server app? i have some minutes trying but nothing, my level of expertise are very low.
When you accept a connection from a client a TcpClient is created. If you want to close that connection then you call Close on that TcpClient.
After tons of coffee cups, boxes of cigarrettes, and an attemp to commit suicide i have this:
Public Sub TerminateClient(Host As String)
For Each client As KeyValuePair(Of TcpClient, HostInfo) In Me.clients
If client.Value.ToString = Host Then
Me.RemoveClient(client.Key)
Exit For
End If
Next
End Sub
I added to MessageServer class. Its right?
Greetings from Venezuela
Does that RemoveClient method call Close on the TcpClient?
Also, from that code alone, it looks like the HostInfo should be the keys and the TcpClient should be the value. Are you using a TcpClient to get a HostInfo from that Dictionary anywhere else? If not then you should switch them.
Let me comment mi Sub. I call RemoveClient, 'cos i observed you call that routine when error occurs on Read sub on MessageServer class. I think this remove client.
Im using the dictionary that is declared at the very beginning of the MessageServer class, is declared in this way:
Private ReadOnly clients As New Dictionary(Of TcpClient, HostInfo)
MessageServer add a element to this dictonary on AcceptTCPClient
'Remember the client and its host information.
Me.clients.Add(client, host)
After studying your code (mainly MessageServer class), i made the routine that i posted before, but i dont know if im in the right path.
Your Message Client-Server is an amazing program that works fine. But, it has some problem with the following issues. Can you tell me how can I fix that?
Problem
When the client computer gets shutdown due to a power lose or something it raises an error.
"IO Exception was unhandled"
Error Message:
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
Your Message Client-Server is an amazing program that works fine. But, it has some problem with the following issues. Can you tell me how can I fix that?
Problem
When the client computer gets shutdown due to a power lose or something it raises an error.
"IO Exception was unhandled"
Error Message:
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
The same happens on the client side too.
Can you fix the problem please?
Thanks in advance.
You can see that there are various exception handlers in the code to handle various situations like that. This sounds like one more like that that you can add for yourself.