OK so I have a program I am working on, its been to bed for about 2 years, my knowledge on the above two was not the greatest, but that I did learn is now rusty, so I come seeking guidance!
I wont post the full project as its a nightmare, but I will provide the key details below in the hope that you may be able to advise.
The Requirements:
I need to open two sockets on two ports.
Socket 1 : sends data over IP/Port does what it needs to do, it needs to be able to hear the messages coming back and send data down. When it hears a keyphrase, the socket will be closed by the other end.
Socket 2 : needs to start with the software, needs to stay open for as long as its left open by the other software. It needs to then be restarted if its disconnected (on demand). This data will be read, and will be used in conjunction with Socket 1 to send data.
In essence this is a 3 way conversation which may go along the lines of the following:
1 Send HI
1 - Recieve Hi
2 - Tell 1 I said Hello
1 - 2 says Hello
1 - Goodbye (closes socket)
2 - I'm still here.
In the meantime, I have been playing and my biggest issue is that If I leave SOcket 2 open, it seems to just loop and doesnt allow me to do anything with my form to start a new interaction, it needs to run independantly and call a routine of a lot of if / else statements to make its next move. I believe this is where threading comes in.
I have two sets of requests that go on, to keep things simple I will refer to them as Socket 1 and Socket 2.
On pressing a button Socket 2 needs to be opened and the app needs to hear what it says, if it says "I'm Here" then thats great. the next job is that Socket 1 needs to be opened and the software needs to send a message to it, this is a 2 fold process: "Open Socket 1" is a routine, it just connects it, "Send Socket 1" is the thread that says "here is the string of data I want you to pass on" and it does so, but I also need for Socket 2 to interrupt in the meantime.
I can open a socket on demand, but if I leave Socket 2 open for example, and the form locks out I am stuffed, or I can open it, get the data, then close it, but that is no good to me.
Can anyone provide a snippet of code around simple terms here that will help me out I will be most appreciative!
"Wisdom is only truly achieved, when you realise you dont know everything" ... I must be a genius because I always have to ask stupid questions...
Pointing an idiot like me in the right direction, is always appreciated by the idiot, explaining how to do what you have pointed the idiot to, is appreciated even more. I apologise to all experienced coders who will think I am an idiot, you are right, I am an idiot, but I am an idiot who is trying to learn
Just adding a little bump to the thread in the hope that someone may have some idea's for me
"Wisdom is only truly achieved, when you realise you dont know everything" ... I must be a genius because I always have to ask stupid questions...
Pointing an idiot like me in the right direction, is always appreciated by the idiot, explaining how to do what you have pointed the idiot to, is appreciated even more. I apologise to all experienced coders who will think I am an idiot, you are right, I am an idiot, but I am an idiot who is trying to learn
Instead of explicit threading, you should use asynchronous techniques that will callback to your code when data is received, clients connect to a listening socket, etc. You tell the socket to statr listening, for example, and your code immediately continues and finishes whatever it was doing, leaving the program free to do other things with the other socket.
As to your protocol, I can't quite understand why you'd create such a system - why can't you simply have one connection?
I think the async technique sounds perfect for my needs, so will try and clarify what I need to do and why in order to see if you can help further.
With regards the double socket, the reason is that the software I communicate on needs to use two sockets. I am basically writing an application that will make my life easier in the long run! the software that I am talking to takes its orders on socket 1 (on a given port) and it gives me updates on socket 2 (a secondary port). Unfortunately this is how the software provider operates and there is no way to just use the one socket, at least, not in a way that completes both tasks that I need to fulfil.
I am trying to write a program that emulates a piece of "till software", so it talks to the card providers software telling it what to do on socket 1, and socket 2 comes back and says I need you to make a decision on X, so I then need to apply logic that then sends my Yes or No decision back down its socket 1. so for all intents and purposes socket 1 is best used as an async connection for a limited duration (the lifetime I want the software to do something) and socket 2 is opened when the program starts, and closes only when the system shuts down. Socket 2 is only ever a one way street, the other software to me.
Hope this makes some sense.
"Wisdom is only truly achieved, when you realise you dont know everything" ... I must be a genius because I always have to ask stupid questions...
Pointing an idiot like me in the right direction, is always appreciated by the idiot, explaining how to do what you have pointed the idiot to, is appreciated even more. I apologise to all experienced coders who will think I am an idiot, you are right, I am an idiot, but I am an idiot who is trying to learn
OK so here is what I have (the attached class) this is a class that someone provided me as a basis and I wonder if you can help me modify it to do what it needs to as it doesnt seem to be doing what I need!
When it comes to managing socket connections, I dont understand the entire premise enough to write my own, which is why a mate threw this together for me!
I believe this is a standard one cap fits all for both sending and receiving? unless someone is able to correct me?
or is it a case that because of the nature I need to use it, I need to call an async seperately for socket 1, but socket 2 needs to be different?
"Wisdom is only truly achieved, when you realise you dont know everything" ... I must be a genius because I always have to ask stupid questions...
Pointing an idiot like me in the right direction, is always appreciated by the idiot, explaining how to do what you have pointed the idiot to, is appreciated even more. I apologise to all experienced coders who will think I am an idiot, you are right, I am an idiot, but I am an idiot who is trying to learn
The only thing that class gives you is splitting received messages on a newline (you can't control the line separator) and lets you send/receive strings by encoding with ASCII (again, not configurable if you need a different encoding). It doesn't handle asynchronicity and doesn't handle listening, it's only a client.
The only thing that class gives you is splitting received messages on a newline (you can't control the line separator) and lets you send/receive strings by encoding with ASCII (again, not configurable if you need a different encoding). It doesn't handle asynchronicity and doesn't handle listening, it's only a client.
Thanks EG, that I suppose is the problem.
I guess the next question is how do I go about building a class that will open and manage sockets the way I need to and also incorporate the management of the data etc?
"Wisdom is only truly achieved, when you realise you dont know everything" ... I must be a genius because I always have to ask stupid questions...
Pointing an idiot like me in the right direction, is always appreciated by the idiot, explaining how to do what you have pointed the idiot to, is appreciated even more. I apologise to all experienced coders who will think I am an idiot, you are right, I am an idiot, but I am an idiot who is trying to learn
I found this on a video tutorial for 2008 http://www.dnrtv.com/default.aspx?showNum=46 howeverm as I am writing on 2010, it did a convert, and all but one thing failed. When I try to run the application, the below appears with an error of two many arguments.
If I can get the below to work on 2010, then I can use it to work through and understand it. If I run the provided exe, it works perfect, but I think its just the transaction of 08 to 10 that is where the
Code:
Imports System.Net
Imports System.net.Sockets
Imports System.IO
Imports System.Windows.Forms
Public Class Form1
Private ClientSocket As Socket
Private recvBuffer(8191) As Byte
Private Sub btnConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConnect.Click
If btnConnect.Text = "Disconnect" Then
Try
SyncLock ClientSocket
ClientSocket.Shutdown(SocketShutdown.Both)
ClientSocket.Close()
End SyncLock
DisconnectedUI()
Catch
End Try
Else
ClientSocket = New Socket(AddressFamily.InterNetwork, _
SocketType.Stream, ProtocolType.Tcp)
Dim address As IPAddress = _
System.Net.Dns.GetHostEntry(txtAddress.Text).AddressList(0)
Dim endpoint As New IPEndPoint(address, CInt(txtPort.Text))
ClientSocket.BeginConnect(endpoint, AddressOf Connected, Nothing)
End If
End Sub
Public Sub Connected(ByVal ar As IAsyncResult)
Try
ClientSocket.EndConnect(ar)
'-- Call ConnectedUI
Dim cb As New SimpleCallback(AddressOf ConnectedUI)
Me.Invoke(cb)
'-- Start Receiving Data
ClientSocket.BeginReceive(recvBuffer, 0, recvBuffer.Length, _
SocketFlags.None, AddressOf ReceivedData, Nothing)
Catch ex As Exception
'-- Call DisconnectedUI
CallDisconnectedUI()
MessageBox.Show(ex.Message)
End Try
End Sub
Public Sub ReceivedData(ByVal ar As IAsyncResult)
Dim numBytes As Int32
Try
SyncLock ClientSocket
numBytes = ClientSocket.EndReceive(ar)
End SyncLock
Catch ex As Exception
CallDisconnectedUI()
Return
End Try
If numBytes = 0 Then
'-- Disconnected!
CallDisconnectedUI()
Return
End If
'-- We have data!
Dim data As String = _
System.Text.ASCIIEncoding.ASCII.GetString(recvBuffer, 0, numBytes)
CallDisplayTextCallback(data)
'-- Start Receiving Data Again!
ClientSocket.BeginReceive(recvBuffer, 0, recvBuffer.Length, _
SocketFlags.None, AddressOf ReceivedData, Nothing)
End Sub
Private Sub CallDisplayTextCallback(ByVal Text As String)
Dim cb As New DisplayTextCallback(AddressOf DisplayText)
Dim args() As Object = {Text}
Me.Invoke(cb, args)
End Sub
Private Delegate Sub DisplayTextCallback(ByVal Text As String)
Public Sub DisplayText(ByVal Text As String)
txtDisplay.AppendText(Text)
txtDisplay.SelectionStart = txtDisplay.Text.Length
End Sub
Private Sub CallDisconnectedUI()
Dim cb As New SimpleCallback(AddressOf DisconnectedUI)
Me.Invoke(cb)
End Sub
Private Delegate Sub SimpleCallback()
Public Sub ConnectedUI()
btnConnect.Text = "Disconnect"
btnSend.Enabled = True
Me.AcceptButton = btnSend
End Sub
Public Sub DisconnectedUI()
btnConnect.Text = "Connect"
btnSend.Enabled = False
Me.AcceptButton = Nothing
End Sub
Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click
'-- Added this code to make it easy for chatting
Dim SendText As String = txtSend.Text
If SendText.EndsWith(vbCrLf) = False Then
SendText &= vbCrLf
End If
Dim bytes() As Byte = _
System.Text.ASCIIEncoding.ASCII.GetBytes(SendText)
SyncLock ClientSocket
ClientSocket.Send(bytes, bytes.Length, SocketFlags.None)
End SyncLock
'-- Added this code to make it easy for chatting
txtSend.Clear()
txtSend.Focus()
End Sub
End Class
Is anyone able to assist in identifying exactly what I need to do to make this work?
"Wisdom is only truly achieved, when you realise you dont know everything" ... I must be a genius because I always have to ask stupid questions...
Pointing an idiot like me in the right direction, is always appreciated by the idiot, explaining how to do what you have pointed the idiot to, is appreciated even more. I apologise to all experienced coders who will think I am an idiot, you are right, I am an idiot, but I am an idiot who is trying to learn
An address incompatible with the requested protocol was used
"Wisdom is only truly achieved, when you realise you dont know everything" ... I must be a genius because I always have to ask stupid questions...
Pointing an idiot like me in the right direction, is always appreciated by the idiot, explaining how to do what you have pointed the idiot to, is appreciated even more. I apologise to all experienced coders who will think I am an idiot, you are right, I am an idiot, but I am an idiot who is trying to learn
That code has a subtle bug in it. When you call BeginXXX, if there is already something waiting to be done (e.g. if you call BeginReceive when there is already some data queued up waiting to be processed) then the callback method is called immediately on the same thread. This increases the stack depth by 1, and the asynchronous callback continue. If it happens again that there is already data waiting to be processed when you call BeginReceive, the stack depth is once more increased by 1. Eventually, if your program runs for long enough and your timing is that unlucky, you'll exhaust the stack and your application will blow up with a StackOverflowException. There is a method to check whether the callback happened immediately and then a correct response to stop the stack increasing, but I can't find my example of how to do so correctly. Hold on and I'll keep searching for it.
Having looked over the code in your referenced post and your explanation, I have to say I am quite confused. I expect that Sockets are too much for my lack of experience in the art of sockets, heck in fact for the majority of .NET, I really am a complete noob at this!
so in the code I am using, your saying that its calling the callback too soon?
I tried to follow your code through but I struggle with it I must admit, these things dont flow as unilaterally as I would like!
I am beginning to think I am well and truely out of my depth and should give up!
"Wisdom is only truly achieved, when you realise you dont know everything" ... I must be a genius because I always have to ask stupid questions...
Pointing an idiot like me in the right direction, is always appreciated by the idiot, explaining how to do what you have pointed the idiot to, is appreciated even more. I apologise to all experienced coders who will think I am an idiot, you are right, I am an idiot, but I am an idiot who is trying to learn
Actually, I think you might not need to deal with this here, as IIRC my testing indicated that BeginReceive never completes synchronously, even if there is data waiting to be received. If a BeginXXX call does complete synchronously, it doesn't call the callback, which is why I have the loop in my sample code. It's this loop that can introduce the stack busting behaviour, and as far as I can remember, it only needed to be dealt with on the server side of a socket when it was accepting connections - if a client was waiting to be accepted, that did complete synchronously.
I've just pasted your code into a VS2010 project, and it didn't show any errors at compile time. What is the exact error you're seeing, and is a compile-time or a runtime error?
So I basically have an application running that has a port on 25000, I run the application, set the IP to 127.0.0.1 and the port as 25000, click connect and it fails at the highlighted line.
"Wisdom is only truly achieved, when you realise you dont know everything" ... I must be a genius because I always have to ask stupid questions...
Pointing an idiot like me in the right direction, is always appreciated by the idiot, explaining how to do what you have pointed the idiot to, is appreciated even more. I apologise to all experienced coders who will think I am an idiot, you are right, I am an idiot, but I am an idiot who is trying to learn
Sorry for the late reply, and thanks again for your ongoing support.
So at the section:
Code:
Private Sub btnConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConnect.Click
If btnConnect.Text = "Disconnect" Then
Try
SyncLock ClientSocket
ClientSocket.Shutdown(SocketShutdown.Both)
ClientSocket.Close()
End SyncLock
DisconnectedUI()
Catch
End Try
Else
ClientSocket = New Socket(AddressFamily.InterNetwork, _
SocketType.Stream, ProtocolType.Tcp)
Dim address As IPAddress = _
System.Net.Dns.GetHostEntry(txtAddress.Text).AddressList(0)
Dim endpoint As New IPEndPoint(address, CInt(txtPort.Text))
ClientSocket.BeginConnect(endpoint, AddressOf Connected, Nothing)
End If
End Sub
I get the error:
Code:
System.Net.Sockets.SocketException was unhandled
ErrorCode=10047
Message=An address incompatible with the requested protocol was used
NativeErrorCode=10047
Source=System
StackTrace:
at System.Net.Sockets.Socket.DoBeginConnect(EndPoint endPointSnapshot, SocketAddress socketAddress, LazyAsyncResult asyncResult)
at System.Net.Sockets.Socket.BeginConnect(EndPoint remoteEP, AsyncCallback callback, Object state)
at SocketsClient.Form1.btnConnect_Click(Object sender, EventArgs e) in D:\Profiles\JamesF5\Downloads\SocketsClient\Form1.vb:line 26
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
at SocketsClient.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
To confirm, I used a freely available socket app, and connected to both ports on the running app and they replied as expected, so it is only the code within that is the issue and the highlighted element.
Thanks
"Wisdom is only truly achieved, when you realise you dont know everything" ... I must be a genius because I always have to ask stupid questions...
Pointing an idiot like me in the right direction, is always appreciated by the idiot, explaining how to do what you have pointed the idiot to, is appreciated even more. I apologise to all experienced coders who will think I am an idiot, you are right, I am an idiot, but I am an idiot who is trying to learn
Is it an IPv4 address in your address textbox? txtPort contains a string convertable to an integer? Check the value in the endpoint variable before executing the erroring line (i.e. put a breakpoint on the erroring line, and use the debugger to check what's in endpoint and that it matches what you'd expect)
I have attached the software I am trying to play with to get this error attached, originally a VS2008 project, I have just tried to click the play button. If you run the exe in the bin folder on XP its fine, on 7 its not.
"Wisdom is only truly achieved, when you realise you dont know everything" ... I must be a genius because I always have to ask stupid questions...
Pointing an idiot like me in the right direction, is always appreciated by the idiot, explaining how to do what you have pointed the idiot to, is appreciated even more. I apologise to all experienced coders who will think I am an idiot, you are right, I am an idiot, but I am an idiot who is trying to learn
You appear to be giving it an IPv6 address, in which case you need to tell the socket that's what sort of address it is by using AddressFamily.InterNetworkV6 rather than AddressFamily.InterNetwork as you have at the moment.
You appear to be giving it an IPv6 address, in which case you need to tell the socket that's what sort of address it is by using AddressFamily.InterNetworkV6 rather than AddressFamily.InterNetwork as you have at the moment.
I honestly wouldnt have had a clue of that so thanks for that EG
Is there a way I can tell it to automatically figure it out? this software will be used across win XP - 8 and I suspect it will go between V4 and V6?
"Wisdom is only truly achieved, when you realise you dont know everything" ... I must be a genius because I always have to ask stupid questions...
Pointing an idiot like me in the right direction, is always appreciated by the idiot, explaining how to do what you have pointed the idiot to, is appreciated even more. I apologise to all experienced coders who will think I am an idiot, you are right, I am an idiot, but I am an idiot who is trying to learn
I honestly wouldnt have had a clue of that so thanks for that EG
Is there a way I can tell it to automatically figure it out? this software will be used across win XP - 8 and I suspect it will go between V4 and V6?
Damn, put the V6 in there and its saying that the machine on both ports is actively refusing it
"Wisdom is only truly achieved, when you realise you dont know everything" ... I must be a genius because I always have to ask stupid questions...
Pointing an idiot like me in the right direction, is always appreciated by the idiot, explaining how to do what you have pointed the idiot to, is appreciated even more. I apologise to all experienced coders who will think I am an idiot, you are right, I am an idiot, but I am an idiot who is trying to learn