3 // We'll use TCP/IP port 5623 for this sample
4 define samplePort = 5623;
6 // We will use this simple structure for our messages
10 // stringLen + 1 bytes are actually used (variable size depending on string)
14 class SampleService : Service
18 // When we get an incoming connection to our service, we spawn a SampleSocket (Can only serve one right now)
21 servingSocket = SampleSocket { this };
22 form.UpdateButtonStates();
27 class SampleSocket : Socket
31 // We want a non blocking Connect() call, so we define an OnConnect() that simply updates the button disabled states
32 form.UpdateButtonStates();
35 void OnDisconnect(int code)
37 // On disconnection we need to null the socket pointers, and update the buttons
38 if(connectedSocket == this)
39 connectedSocket = null;
40 else if(servingSocket == this)
43 form.UpdateButtonStates();
46 unsigned int OnReceive(unsigned char * buffer, unsigned int count)
48 // We only process the data if we've received enough bytes to make up the message
49 // This first if just checks if we have reveived enough bytes for the header
50 if(count >= sizeof(SamplePacket))
52 SamplePacket * packet = (SamplePacket *) buffer;
53 uint size = sizeof(SamplePacket) + packet->stringLen;
54 // Here we check if we've actually received the entire message
57 // We've received a complete message, so we change the contents of the recvString EditBox
58 form.recvString.contents = packet->string;
59 // and we return the size of the message we've processed.
60 // If more data is already buffered, this method will be called again right away.
64 // We haven't received enough data to process this message yet: return 0 bytes processed
65 // This method will be called again once more data has been received.
70 class SocketSample : Window
72 text = "Socket Sample";
73 background = activeBorder;
74 borderStyle = sizable;
80 nativeDecorations = true;
82 // Service is missing a property to tell us if it's listening or not already, so we keep track of it in this variable
85 void UpdateButtonStates()
87 bool connected = (connectedSocket && connectedSocket.connected) || (servingSocket && servingSocket.connected);
89 // The Send button is disabled if we're not connected
90 btnSend.disabled = !connected;
91 // The Connect button is disabled if we've already defined a connectedSocket
92 btnConnect.disabled = connectedSocket != null;
93 // The Listen button is disabled if we're already listening
94 btnListen.disabled = listening;
99 this, text = "Send", position = { 344, 64 }, disabled = true;
101 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
103 // We build up a SamplePacket here with our message from the sentString EditBox
104 String string = sentString.contents;
105 int len = strlen(string);
106 int size = sizeof(SamplePacket) + len;
107 SamplePacket * packet = (SamplePacket *)new byte[size];
108 packet->stringLen = len;
109 memcpy(packet->string, string, len+1);
110 // If we've connected to another server, we use the connectedSocket, otherwise we use the servingSocket (Send back to whom connected to us)
111 (connectedSocket ? connectedSocket : servingSocket).Send(packet, size);
112 // Make sure to free memory allocated with 'new'
117 EditBox serverAddress { this, text = "Server Address", size = { 174, 19 }, position = { 8, 40 }, contents = "localhost" };
118 Label lblServerAddress { this, position = { 8, 16 }, labeledWindow = serverAddress };
121 this, text = "Listen", position = { 144, 104 };
123 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
125 // Start listening here
129 UpdateButtonStates();
134 EditBox sentString { this, text = "Sent String", size = { 166, 19 }, position = { 224, 40 } };
135 Label lblSentString { this, position = { 224, 16 }, labeledWindow = sentString };
136 EditBox recvString { this, text = "Received String", size = { 166, 19 }, position = { 224, 104 } };
137 Label label1 { this, position = { 224, 80 }, labeledWindow = recvString };
140 this, text = "Connect", position = { 8, 72 };
142 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
144 btnConnect.disabled = true;
145 // Create a socket and attempt a connection to the address specified in the serverAddress EditBox
146 connectedSocket = SampleSocket { };
147 // Connect is a blocking call if no OnConnect method is defined in the Socket, a non-blocking call otherwise
148 connectedSocket.Connect(serverAddress.contents, samplePort);
155 // We need to disconnect the socket and stop the service before destroying the application,
156 // otherwise we'll get a crash with the SampleSocket accessing the form that is already destroyed
158 connectedSocket.Disconnect(0);
164 SocketSample form {};
167 SampleService service { port = samplePort };
169 // We use 2 sockets: one for when we connect to a server, one for the incoming connections to our SampleService
170 SampleSocket connectedSocket, servingSocket;