This example shows how to use
non-GUI .NET components.
The .NET Framework contains
easy to use classes for TCP Socket communication (TcpClient and
TcpListener). These components can be used in simple scenarios where
synchronous (blocking) operation is acceptable. It is also possible to
use the low-level Socket class both for synchronous and asynchronous
communication. The asynchronous use of socket communication in .NET is
not very difficult, but it can be dangerous to use it in a windowed
environment without handling the multithreaded issues properly. The
asynchronous mode operation is based on callbacks, and these callbacks
are normally called on another thread than the primary thread for the
window application. If the callback calls into code that manipulates any
window control, the single threaded use of Win32 is violated. This will
result in bugs that are difficult to track down and correct.
Tordivel has developed a
socket communication component that ensure that all callbacks are routed
to events that are called on the main thread of the application. The
RawTcpMessenger component can act both as a socket communication server
(listen for connections) and a socket communication client.
Here is the user interface created for
demonstration purposes by the following script.
A separate test/demo program for RawTcpMessenger
is also enclosed with the RawTcpMessenger profile.
# Python start script
goes here
print 'Central Start'
import CLR
import CLR.System.Windows.Forms as WinForms
from CLR.System.Text import Encoding
from CLR.System.Net import Dns, IPHostEntry, IPEndPoint, IPAddress
from CLR.System.Drawing import Size, Point, ContentAlignment, Font
from CLR.System import Int32, Decimal
# Load custom assemblies
from CLR.System.Reflection import Assembly
scorpionDir = GetValue('System.ScorpionDir')
Assembly.LoadFrom(scorpionDir + r'\OverlayPanel.dll')
from CLR.Tordivel import OverlayPanel
# Custom .NET components should be placed in DotNet folder in profile
path
profile = GetValue('System.Profile')
Assembly.LoadFrom(profile + r'\DotNet\RawTcpMessenger.dll')
from CLR.Tordivel import RawTcpMessenger
class ResultPanelOverlay(OverlayPanel):
def __init__(self,nativeParentHandleAsInt32):
self.Dock = WinForms.DockStyle.Fill
# Show Debug Trace from .NET Code
#self.ShowTrace = 1
# Create the errorProvider control
self.errorProvider = WinForms.ErrorProvider()
self.errorProvider.BlinkStyle =
WinForms.ErrorBlinkStyle.NeverBlink
# Get local ip address (use first in list if many)
hostName = Dns.GetHostName()
iphostentry = Dns.GetHostByName(hostName)
self.localAddress = iphostentry.AddressList[0].ToString()
# Create the RawTcpMessenger component
self.rawTcpMessenger = RawTcpMessenger(self)
# Register handler for rawTcpMessenger.Receive event
self.rawTcpMessenger.Receive +=
self.rawTcpMessenger_ReceiveHandler
# Register handler for rawTcpMessenger.RemoteConnect event
self.rawTcpMessenger.RemoteConnect +=
self.rawTcpMessenger_RemoteConnectHandler
# Register handler for rawTcpMessenger.RemoteDisconnect event
self.rawTcpMessenger.RemoteDisconnect +=
self.rawTcpMessenger_RemoteDisconnectHandler
# Register handler for rawTcpMessenger.SendError event
self.rawTcpMessenger.SendError +=
self.rawTcpMessenger_SendErrorHandler
# Create the listenAddressTextBox
self.listenAddressTextBox = WinForms.TextBox()
self.listenAddressTextBox.Parent = self
self.listenAddressTextBox.Size = Size(100,25)
self.listenAddressTextBox.Location = Point(115,12)
self.listenAddressTextBox.Text = self.localAddress
self.listenAddressTextBox.ReadOnly = 1
# Create the listenAddressLabel (after the
listenAddressTextBox to avoid hiding)
self.listenAddressLabel = WinForms.Label()
self.listenAddressLabel.Parent = self
self.listenAddressLabel.Size = Size(120,25)
self.listenAddressLabel.Location = Point(10,10)
self.listenAddressLabel.Text = "Listen address:"
self.listenAddressLabel.TextAlign =
ContentAlignment.MiddleLeft
# Create the listenPortUpDown
self.listenPortUpDown = WinForms.NumericUpDown()
self.listenPortUpDown.Parent = self
self.listenPortUpDown.Size = Size(80,25)
self.listenPortUpDown.Location = Point(320,12)
self.listenPortUpDown.Minimum = Decimal(1000)
self.listenPortUpDown.Maximum = Decimal(100000)
self.listenPortUpDown.ReadOnly = 1
# Register event handler for listenPortUpDown.ValueChanged
self.listenPortUpDown.ValueChanged +=
self.listenPortUpDown_ValueChangedHandler
# Set the value after registering the value changed event
handler
self.listenPortUpDown.Value = Decimal(12345)
# Create the listenPortLabel (after the listenPortTextBox to
avoid hiding)
self.listenPortLabel = WinForms.Label()
self.listenPortLabel.Parent = self
self.listenPortLabel.Size = Size(120,25)
self.listenPortLabel.Location = Point(230,10)
self.listenPortLabel.Text = "Listen port:"
self.listenPortLabel.TextAlign = ContentAlignment.MiddleLeft
# Create the destinationAddressTextBox
self.destinationAddressTextBox = WinForms.TextBox()
self.destinationAddressTextBox.Parent = self
self.destinationAddressTextBox.Size = Size(100,25)
self.destinationAddressTextBox.Location = Point(115,42)
self.destinationAddressTextBox.Text = self.localAddress
# Create the destinationAddressLabel (after the
destinationAddressTextBox to avoid hiding)
self.destinationAddressLabel = WinForms.Label()
self.destinationAddressLabel.Parent = self
self.destinationAddressLabel.Size = Size(120,25)
self.destinationAddressLabel.Location = Point(10,40)
self.destinationAddressLabel.Text = "Destination address:"
self.destinationAddressLabel.TextAlign =
ContentAlignment.MiddleLeft
# Create the destinationPortUpDown
self.destinationPortUpDown = WinForms.NumericUpDown()
self.destinationPortUpDown.Parent = self
self.destinationPortUpDown.Size = Size(80,25)
self.destinationPortUpDown.Location = Point(320,42)
self.destinationPortUpDown.Minimum = Decimal(1000)
self.destinationPortUpDown.Maximum = Decimal(100000)
self.destinationPortUpDown.Value = Decimal(12346)
# Register event handler for
destinationPortUpDown.ValueChanged
self.destinationPortUpDown.ValueChanged +=
self.destinationPortUpDown_ValueChangedHandler
# Create the destinationPortLabel (after the
destinationPortUpDown to avoid hiding)
self.destinationPortLabel = WinForms.Label()
self.destinationPortLabel.Parent = self
self.destinationPortLabel.Size = Size(120,25)
self.destinationPortLabel.Location = Point(230,40)
self.destinationPortLabel.Text = "Destination port:"
self.destinationPortLabel.TextAlign =
ContentAlignment.MiddleLeft
# Create the connectCheckBox
self.connectCheckBox = WinForms.CheckBox()
self.connectCheckBox.Parent = self
self.connectCheckBox.Appearance = WinForms.Appearance.Button
self.connectCheckBox.Size = Size(60,22)
self.connectCheckBox.Location = Point(405,42)
self.connectCheckBox.Text = "Connect"
self.connectCheckBox.TextAlign =
ContentAlignment.MiddleCenter
# Register event handler for connectCheckBox.Click
self.connectCheckBox.Click +=
self.connectCheckBox_ClickHandler
# Create the messageTextBox
self.messageTextBox = WinForms.TextBox()
self.messageTextBox.Parent = self
self.messageTextBox.Size = Size(260,25)
self.messageTextBox.Location = Point(70,82)
self.messageTextBox.Text = "Hello"
# Create the messageLabel (after the messageTextBox to avoid
hiding)
self.messageLabel = WinForms.Label()
self.messageLabel.Parent = self
self.messageLabel.Size = Size(100,25)
self.messageLabel.Location = Point(10,80)
self.messageLabel.Text = "Message:"
self.messageLabel.TextAlign = ContentAlignment.MiddleLeft
# Create the sendButton
self.sendButton = WinForms.Button()
self.sendButton.Parent = self
self.sendButton.Size = Size(60,22)
self.sendButton.Location = Point(340,80)
self.sendButton.Text = "Send"
# Register event handler for sendButton.Click
self.sendButton.Click += self.sendButton_ClickHandler
# Create the listbox
self.listBox = WinForms.ListBox()
self.listBox.Parent = self
self.listBox.Size = Size(480,250)
self.listBox.Location = Point(10,120)
self.listBox.Sorted = 0
def listenPortUpDown_ValueChangedHandler(self, sender, args):
# Handles the listenPortUpDown ValueChanged event
listenPort = Decimal.ToInt32(self.listenPortUpDown.Value)
if
self.rawTcpMessenger.StartListen(self.localAddress,listenPort):
self.errorProvider.SetError(self.listenPortUpDown,"")
else:
self.errorProvider.SetError(self.listenPortUpDown,"Can
NOT Listen")
def destinationPortUpDown_ValueChangedHandler(self, sender, args):
# Handles the destinationPortUpDown ValueChanged event
self.errorProvider.SetError(self.connectCheckBox,"");
destinationAddress = self.destinationAddressTextBox.Text
destinationPort =
Decimal.ToInt32(self.destinationPortUpDown.Value)
self.connectCheckBox.Checked =
self.rawTcpMessenger.IsConnected(destinationAddress,destinationPort)
def connectCheckBox_ClickHandler(self, sender, args):
# Handles the connectButton Click event
self.errorProvider.SetError(self.connectCheckBox,"");
destinationAddress = self.destinationAddressTextBox.Text
destinationPort =
Decimal.ToInt32(self.destinationPortUpDown.Value)
if self.connectCheckBox.Checked:
if
self.rawTcpMessenger.IsConnected(destinationAddress,destinationPort) !=
1:
if
self.rawTcpMessenger.Connect(destinationAddress,destinationPort) != 1:
self.errorProvider.SetError(connectCheckBox,"Connect Failed")
else:
self.rawTcpMessenger.Disconnect(destinationAddress,destinationPort)
def sendButton_ClickHandler(self, sender, args):
# Handles the sendButton Click event
destinationAddress = self.destinationAddressTextBox.Text
destinationPort =
Decimal.ToInt32(self.destinationPortUpDown.Value)
messageText = self.messageTextBox.Text
self.rawTcpMessenger.Send(destinationAddress,destinationPort,Encoding.ASCII.GetBytes
(self.messageTextBox.Text))
def rawTcpMessenger_ReceiveHandler(self, sender, args):
# Handles the rawTcpMessenger Receive event
messageText = args.senderAddress + ":" + str(args.senderPort)
+ " " + Encoding.ASCII.GetString (args.message,0,args.message.Length)
self.listBox.Items.Add(messageText)
def rawTcpMessenger_RemoteConnectHandler(self, sender, args):
# Handles the tcpMessenger RemoteConnect event
messageText = args.remoteAddress + ":" + str(args.remotePort)
+ " Connected"
self.listBox.Items.Add(messageText)
def rawTcpMessenger_RemoteDisconnectHandler(self, sender, args):
# Handles the tcpMessenger RemoteDisconnect event
messageText = args.remoteAddress + ":" + str(args.remotePort)
+ " Disconnected"
self.listBox.Items.Add(messageText)
def rawTcpMessenger_SendErrorHandler(self, sender, args):
# Handles the tcpMessenger SendError event
messageText = args.remoteAddress + ":" + str(args.remotePort)
+ " SendError: " + args.errorDescription
self.listBox.Items.Add(messageText)
# try to close existing RawTcpMessenger
try:
resultPanelOverlay.rawTcpMessenger.Close()
resultPanelOverlay.Dispose()
except:
print 'Dispose Failed'
# Create global instance of resultPanelOverlay
resultPanelOverlay = ResultPanelOverlay(GetResultPanel().handle)
|