This is a PowerBASIC Console Compiler translation of the original codeproject C source code (http://"http://www.codeproject.com/Articles/11740/A-simple-UDP-time-server-and-client-for-beginners"),
using UDP to send datagram between a server and client on a local network, using port 8000.
Server code
'// A simple UDP server that sends the current date and time to the client
'// Original code: http://www.codeproject.com/Articles/11740/A-simple-UDP-time-server-and-client-for-beginners
'// Translated from C to PowerBASIC by Patrice Terrier
'// Date: 09-29-2015
#BREAK ON
#COMPILE EXE "TimeServer.exe"
#Include "win32api.inc"
#Include "time.inc"
%NULL = 0
%BUFFER_SIZE = 4096
%PORT_NUMBER = 8000 '// Port number to use
declare function my_inet_ntoa lib "wsock32.dll" alias "inet_ntoa" (byval inn as dword) as dword
function pbmain() as long
local wsa as WSADATA '// Used to open windows connection
local client_length as long '// Length of client struct
local bytes_received as long '// Bytes received from client
local lps as DWORD '// Socket descriptor of server
local serverinfo as sockaddr_in '// Information about the server
local clientinfo as sockaddr_in '// Information about the client
local buffer as asciiz * %BUFFER_SIZE '// Where to store received data
local hp as hostent PTR '// Information about this computer
local host_name as asciiz * 256 '// Name of the serverinfo
local current_time as long '// Current time
'// Open windows connection
if (WSAStartup(&h0202, wsa)) then
print "Could not open Windows connection."
function = 0: exit function
end if
'// Open a datagram socket
lps = socket(%AF_INET, %SOCK_DGRAM, byval %NULL)
if (lps = %INVALID_SOCKET) then
print "Could not create socket."
else
'// Clear out server struct
RtlFillMemory(byval varptr(serverinfo), sizeof(sockaddr_in), 0)
'// Set family and port
serverinfo.sin_family = %AF_INET
serverinfo.sin_port = htons(%PORT_NUMBER)
'// Set address automatically
gethostname(host_name, sizeof(host_name))
hp = gethostbyname(host_name)
'// Check for %NULL pointer
if (hp = %NULL) then
print "Could not get host name."
else
local h as hostent, IPaddr as byte ptr
MoveMemory(byval varptr(h), byval hp, sizeof(hostent))
MoveMemory(byval varptr(IPaddr), byval h.h_addr_list, 4)
dim n(0 to 3) as byte at IPaddr
'// Assign the address
serverinfo.sin_addr.S_un.S_un_b.s_b1 = n(0)
serverinfo.sin_addr.S_un.S_un_b.s_b2 = n(1)
serverinfo.sin_addr.S_un.S_un_b.s_b3 = n(2)
serverinfo.sin_addr.S_un.S_un_b.s_b4 = n(3)
'// Bind address to socket
if (bind(lps, serverinfo, sizeof(sockaddr_in)) = -1) then
print "Could not bind name to socket."
else
'// Print out serverinfo information
local ptrAddr as dword ptr, ptrAsciiz as asciiz ptr
ptrAddr = @hp.h_addr_list
ptrAsciiz = my_inet_ntoa(@@ptrAddr)
print "server running on " + @ptrAsciiz
print "Press Ctrl+Break or Ctrl+Pause/Attn to quit"
local zTime as asciiz * 8
client_length = sizeof(sockaddr_in)
'// Loop and get data from clients
do
'// Receive bytes from client
bytes_received = recvfrom(lps, buffer, %BUFFER_SIZE, byval 0, clientinfo, client_length)
if (bytes_received < 0) then
print "Could not receive datagram.": exit do
else
'// Check for time request
if (rtrim$(buffer, chr$(13,10)) = "GET TIME") then
'// Get current time
current_time = time(0)
RtlFillMemory(byval varptr(zTime), sizeof(zTime), 0)
MoveMemory(byval varptr(zTime), byval varptr(current_time), 4)
ptrAsciiz = ctime(current_time)
print "Sending current time: " + rtrim$(@ptrAsciiz, any chr$(0,10,13))
'// Send data back
if (sendto(lps, zTime, sizeof(zTime), 0, clientinfo, client_length) <> sizeof(zTime)) then
print "Error sending datagram.": exit do
end if
end if
end if
loop
end if
end if
closesocket(lps)
end if
WSACleanup()
function = 0
end function
Client code
'// Gets the current time from a UDP server
'// Original code: http://www.codeproject.com/Articles/11740/A-simple-UDP-time-server-and-client-for-beginners
'// Translated from C to PowerBASIC by Patrice Terrier
'// Date: 09-29-2015
#BREAK ON
#COMPILE EXE "TimeClient.exe"
#Include "win32api.inc"
#Include "time.inc"
%NULL = 0
%BUFFER_SIZE = 4096
%PORT_NUMBER = 8000 '// Port number to use
function pbmain() as long
local wsa as WSADATA '// Used to open windows connection
local server_length as long '// Length of server struct
local lps as DWORD '// Socket descriptor
local serverinfo as sockaddr_in '// Information about the server
local clientinfo as sockaddr_in '// Information about the client
local buffer as asciiz * %BUFFER_SIZE '// Where to store received data
local hp as hostent PTR '// Information about the server
local host_name as asciiz * 256 '// Name of the serverinfo
local current_time as long '// Time received
dim a(1 to 4) as byte '// Server address components in xxx.xxx.xxx.xxx form
local K as long
'// Make sure command line is correct
if (parsecount(command$, ".") <> 4) then
print "Usage: TimeClient server_adress(xxx.xxx.xxx.xxx)."
function = 0: exit function
else
for K = 1 to 4
a(K)= val(parse$(command$, ".", K))
next
end if
'// Open windows connection
if (WSAStartup(&h0202, wsa)) then
print "Could not open Windows connection."
function = 0: exit function
end if
'// Open a datagram socket
lps = socket(%AF_INET, %SOCK_DGRAM, byval %NULL)
if (lps = %INVALID_SOCKET) then
print "Could not create socket."
else
'// Clear out server struct
RtlFillMemory(byval varptr(serverinfo), sizeof(sockaddr_in), 0)
'// Set family and port
serverinfo.sin_family = %AF_INET
serverinfo.sin_port = htons(%PORT_NUMBER)
'// Set server address
serverinfo.sin_addr.S_un.S_un_b.s_b1 = a(1)
serverinfo.sin_addr.S_un.S_un_b.s_b2 = a(2)
serverinfo.sin_addr.S_un.S_un_b.s_b3 = a(3)
serverinfo.sin_addr.S_un.S_un_b.s_b4 = a(4)
'// Clear out client struct
RtlFillMemory(byval varptr(clientinfo), sizeof(sockaddr_in), 0)
'// Set family and port
clientinfo.sin_family = %AF_INET
clientinfo.sin_port = htons(0)
gethostname(host_name, sizeof(host_name))
hp = gethostbyname(host_name)
'// Check for %NULL pointer
if (hp = %NULL) then
print "Could not get host name."
else
local h as hostent, IPaddr as byte ptr
MoveMemory(byval varptr(h), byval hp, sizeof(hostent))
MoveMemory(byval varptr(IPaddr), byval h.h_addr_list, 4)
dim n(1 to 4) as byte at IPaddr
'// Assign the address
clientinfo.sin_addr.S_un.S_un_b.s_b1 = n(1)
clientinfo.sin_addr.S_un.S_un_b.s_b2 = n(2)
clientinfo.sin_addr.S_un.S_un_b.s_b3 = n(3)
clientinfo.sin_addr.S_un.S_un_b.s_b4 = n(4)
'// Bind local address to socket
if (bind(lps, clientinfo, sizeof(sockaddr_in)) = -1) then
print "Cannot bind address to socket."
else
'// Tranmsit data to get time
server_length = sizeof(sockaddr_in)
buffer = "GET TIME"
if (sendto(lps, buffer, sizeof(buffer), 0, serverinfo, server_length) < 0) then
print "Error transmitting data."
else
'// Receive time
local zTime as asciiz * 8
if (recvfrom(lps, zTime, sizeof(zTime), 0, serverinfo, server_length) < 0) then
print "Error receiving data."
else
'// Display time
MoveMemory(byval varptr(current_time), byval varptr(zTime), 4)
local ptrAsciiz as asciiz ptr: ptrAsciiz = ctime(current_time)
print "Server time is: " + rtrim$(@ptrAsciiz, any chr$(0,10,13))
end if
end if
end if
end if
closesocket(lps)
end if
WSACleanup()
function = 0
end function
Usage:
On server run "TimeServer" from a DOS prompt.
On client run "TimeClient xxx.xxx.xxx.xxx" from a DOS prompt where xxx.xxx.xxx.xxx matches the address displayed by TimeServer.
To shut down TimeServer, press Ctrl+Break.
Note: The EXE(s) from the attached zip file, have been created with PBCC 7.0 (beta) and using José Roca's include files.
...
Thanks very much. Very useful.