Author Topic: Winsock functions with OxygenBasic  (Read 8473 times)

0 Members and 1 Guest are viewing this topic.

Arnold

  • Guest
Winsock functions with OxygenBasic
« on: July 17, 2015, 12:56:16 AM »
Hi,

John has posted some interesting code with his thesaurus project which I would apply in Oxygenbasic. Therefore I searched in Internet for some examples using Winsock functions. I am not interested to create a library (there is too much to be considered), only for some functionality on the client's side. Until now I can connect to a server, send and receive some data. But there are some promblems, maybe somebody with more experience can help me a little bit?

This is what I have done until now:
Code: OxygenBasic
  1. 'Connect to server, send and receive data
  2. 'uses IP address in IPv4 format
  3.  
  4. include "$/inc/console.inc"
  5.  
  6.  
  7. % SOCKET_ERROR          = -1
  8. % SOCK_STREAM           = 1
  9. % AF_INET               = 2
  10. % INVALID_SOCKET        = 0xFFFFFFFF
  11. % MSG_WAITALL           = 0x8
  12.  
  13. typedef sys WSOCKET
  14.  
  15.  
  16. type WSADATA 'Requires Windows Sockets 2.0
  17.  wVersion       as word          'WORD ( = 0x0202)                      
  18.  wHighVersion   as word          'WORD ( = 0x0202)                      
  19.  szDescription  as zString * 257 'char [WSADESCRIPTION_LEN+1]
  20.  szSystemStatus as zString * 129 'char [WSASYS_STATUS_LEN+1]  
  21.  iMaxSockets    as short         'unsigned short
  22.  iMaxUdpDg      as short         'unsigned short
  23.  lpVendorInfo   as Long         'char far*
  24. end type
  25. /*
  26. typedef struct in_addr {
  27.   union {
  28.     struct {
  29.       u_char s_b1,s_b2,s_b3,s_b4;
  30.     } S_un_b;
  31.     struct {
  32.       u_short s_w1,s_w2;
  33.     } S_un_w;
  34.     u_long S_addr;
  35.   } S_un;
  36. } IN_ADDR, *PIN_ADDR FAR *LPIN_ADDR;
  37. */
  38.  
  39. 'type in_addr
  40.  union in_addr 's_un
  41.  {
  42.     type s_un_b
  43.     {
  44.       byte s_b1
  45.       byte s_b2
  46.       byte s_b3
  47.       byte s_b4
  48.     }
  49.     type s_un_w
  50.     {
  51.       short s_w1
  52.       short s_w2
  53.     }
  54.     long s_addr
  55.   }
  56. 'end type
  57.  
  58. struct sockaddr {
  59.     short    sa_family    ' address family, AF_xxx
  60.    char     sa_data[14]  ' 14 bytes of protocol address}
  61. }
  62.  
  63.  
  64. ' IPv4 AF_INET sockets:
  65. type sockaddr_in
  66.     sin_family as short   ' e.g. AF_INET, AF_INET6
  67.    sin_port as short     ' e.g. htons(3490)
  68.    sin_addr as in_addr   ' see struct in_addr, below
  69.    sin_zero[8] as char   ' zero this if you want to
  70. end type
  71.  
  72.  
  73. 'SELECTED PROCEDURES
  74. ====================
  75.  
  76. extern lib "ws2_32.dll"
  77.  
  78. ! WSAStartup (word wVersionRequested, WSADATA *lpWSAData) as int
  79. ! WSAGetLastError () as int
  80. ! socket(int af, int type, int protocol) as WSOCKET
  81. ! closesocket(WSOCKET s) as int
  82. ! WSACleanup () as int
  83. ! inet_addr (char *cp) as u_long 'cp: NULL-terminated character string representing a number expressed in the Internet standard ".'' (dotted) notation.
  84. ! htons(short hostshort) as short 'returns the value in TCP/IP network byte order
  85. ! connect(WSOCKET hSocket, sys *Name, int namelen) as int 'returns zero if no error
  86. ! send(WSOCKET s, char *buf, int len, int flags) as int
  87. ! recv(WSOCKET s, char *buf, int len, int flags) as int
  88.  
  89. end extern
  90.  
  91.  
  92. sub main()
  93.  
  94.    WSADATA wsa
  95.    WSOCKET s    
  96.    sockaddr_in server
  97.    string message
  98.    string server_reply = nuls 4000
  99.    int recv_size = 0
  100.            
  101.  
  102.    print cr & "Initialising Winsock..." & cr    
  103.    if WSAStartup(0x0202, wsa) != 0 then    
  104.       print "Failed. Error Code : " WSAGetLastError() & cr        
  105.       exit sub    
  106.    end if        
  107.  
  108.    print "Initialised." & cr
  109.  
  110.    ' Create a TCP socket
  111.  
  112.    s = socket(AF_INET , SOCK_STREAM , 0 )  
  113.  
  114.    if s = INVALID_SOCKET then    
  115.       print "Could not create socket : "   WSAGetLastError() & cr
  116.       exit sub    
  117.    end if  
  118.    print "Socket created." & cr
  119.  
  120.    server.sin_addr.s_addr = inet_addr("216.18.20.172") ' dict.org  
  121.   server.sin_family = AF_INET    
  122.    server.sin_port = htons( 2628 )
  123.  
  124.    ' Connect to remote server
  125.  
  126.    if connect(s , &server , sizeof(sockaddr)) < 0 then  
  127.       print "connect error" & cr      
  128.       exit sub    
  129.    end if
  130.  
  131.    print "Connected" & cr & cr
  132.  
  133.    ' Send some data    
  134.   message = "SHOW DB" & cr
  135.    result = send(s , message , len(message) , 0)    
  136.    if result < 0 then            
  137.       print "Send failed" & cr        
  138.       exit sub    
  139.    end if  
  140.    print "Data Send (SHOW DB)" & cr
  141.  
  142.    ' Receive a reply from the server
  143.   recv_size = recv(s , server_reply , 4000 , 0)  
  144.    if recv_size  = SOCKET_ERROR then    
  145.       print "recv failed" & cr    
  146.    end if        
  147.    print "Reply received" & cr & cr
  148.    
  149.    ' print first reply
  150.   print left(server_reply, recv_size)
  151.    print cr
  152.  
  153.    ' send next message
  154.   message = "SHOW DATABASE" & cr
  155.    result = send(s , message , len(message) , 0)
  156.    if result < 0 then            
  157.       print "Send failed" & cr        
  158.       exit sub    
  159.    end if  
  160.    print "Send message (SHOW DATABASE) and receive reply:" & cr & cr
  161.  
  162.    recv_size = recv(s , server_reply , 4000 , 0)
  163.    if recv_size  = SOCKET_ERROR then    
  164.       print "recv failed" & cr    
  165.    end if        
  166.    print "Reply received" & cr & cr
  167.    print  left(server_reply, recv_size)
  168.    print cr
  169.  
  170.    message = "QUIT"  & cr
  171.    result = send(s , message , len(message) , 0)
  172.    if result < 0 then            
  173.       print "Send failed" & cr        
  174.       exit sub    
  175.    end if  
  176.    print "Send QUIT message" & cr
  177.  
  178.    recv_size = recv(s , server_reply , 4000 , 0)
  179.    print "Reply received" & cr & cr
  180.    print  left(server_reply, recv_size)
  181.    print cr
  182.  
  183.    closesocket(s)
  184.    WSACleanup()
  185.  
  186.    print "Socket closed" & cr
  187.  
  188. end sub
  189.  
  190.  
  191. main()
  192.  
  193. printl "Enter ..." : waitkey()
  194.  

Although my notebook is not very fast, sending the messages will take place although receiving the data is not yet finished. (250 ok is the end of the expected data). What could I do to receive the complete package at once?

Until now I did also not succeed to apply gethostbyname to resolve e.g. "www.dict.org" to an IPv4 dotted address. Does anybody know how to do this in basic? I used nslookup.exe to do this.


Roland



.
« Last Edit: July 25, 2015, 02:56:46 AM by Arnold »

JRS

  • Guest
Re: Winsock functions with OxygenBasic
« Reply #1 on: July 17, 2015, 08:09:29 PM »
Have you tried using cURL?

C BASIC cURL wget like example.
« Last Edit: July 17, 2015, 11:19:51 PM by John »

Arnold

  • Guest
Re: Winsock functions with OxygenBasic - gethostbyname
« Reply #2 on: July 20, 2015, 06:57:52 AM »
Hi Charles,

I will need some of your help because I definitely do not know what I am doing (although it works in some way). Experimenting with the gethostbyname function I tried to replicate this example:

Running my code the third result is the same which I get e.g. with nslookup dict.org. But I do not know the meaning of the first two results. Moreover e.g. with google.com there should be more results, but with me there is garbage starting with the fourth result.

Is there something wrong with my declaring the types (hostent, in_addr) and with the function inet_ntoa? I am afraid I have some problems with pointers to pointers constructs.

This is what works so far:

Code: OxygenBasic
  1. include "$/inc/console.inc"
  2.  
  3. /* Get IP address from domain name */
  4.  
  5. % SOCKET_ERROR          = -1
  6. % SOCK_STREAM           = 1
  7. % AF_INET               = 2
  8. % AF_NETBIOS            = 17
  9. % INVALID_SOCKET        = 0xFFFFFFFF
  10. % MSG_WAITALL           = 0x8
  11.  
  12. typedef sys WSOCKET
  13.  
  14.  
  15. type WSADATA 'Requires Windows Sockets 2.0
  16.  wVersion       as word          'WORD ( = 0x0202)                      
  17.  wHighVersion   as word          'WORD ( = 0x0202)                      
  18.  szDescription  as zString * 257 'char [WSADESCRIPTION_LEN+1]
  19.  szSystemStatus as zString * 129 'char [WSASYS_STATUS_LEN+1]  
  20.  iMaxSockets    as short         'unsigned short
  21.  iMaxUdpDg      as short         'unsigned short
  22.  lpVendorInfo   as Long          'char far*
  23. end type
  24.  
  25. /*
  26. typedef struct in_addr {
  27.   union {
  28.     struct {
  29.       u_char s_b1,s_b2,s_b3,s_b4;
  30.     } S_un_b;
  31.     struct {
  32.       u_short s_w1,s_w2;
  33.     } S_un_w;
  34.     u_long S_addr;
  35.   } S_un;
  36. } IN_ADDR, *PIN_ADDR, *LPIN_ADDR;
  37. */
  38.  
  39. 'type in_addr
  40.  union in_addr 's_un
  41.  {
  42.     type s_un_b
  43.     {
  44.       byte s_b1
  45.       byte s_b2
  46.       byte s_b3
  47.       byte s_b4
  48.     }
  49.     type s_un_w
  50.     {
  51.       short s_w1
  52.       short s_w2
  53.     }
  54.     sys s_addr
  55.   }
  56. 'end type
  57.  
  58. struct sockaddr {
  59.     short    sa_family    // address family, AF_xxx
  60.     char       sa_data[14]  // 14 bytes of protocol address}
  61. }
  62.  
  63.  
  64. // IPv4 AF_INET sockets:
  65. type sockaddr_in
  66.     sin_family as short   // e.g. AF_INET, AF_INET6
  67.     sin_port as short     // e.g. htons(3490)
  68.     sin_addr as in_addr   // see struct in_addr, below
  69.     sin_zero[8] as char   // zero this if you want to
  70. end type
  71.  
  72. /*
  73. typedef struct hostent {
  74.   char FAR      *h_name;
  75.   char FAR  FAR **h_aliases;
  76.   short         h_addrtype;
  77.   short         h_length;
  78.   char FAR  FAR **h_addr_list;
  79. } HOSTENT, *PHOSTENT, FAR *LPHOSTENT;
  80. */
  81.  
  82. type hostent
  83.    char    *h_name
  84.    sys     *h_aliases
  85.    short   h_addrtype
  86.    short   h_length
  87.    in_addr *h_addr_list 'list of in_addr (s_addr is needed)
  88. end type
  89.  
  90. 'print "sizeof(hostent): " sizeof(hostent) & cr & cr
  91.  
  92. 'SELECTED PROCEDURES
  93. ====================
  94.  
  95. extern lib "ws2_32.dll"
  96.  
  97. ! WSAStartup (word wVersionRequested, WSADATA *lpWSAData) as int
  98. ! WSAGetLastError () as int
  99. ! socket(int af, int type, int protocol) as WSOCKET
  100. ! closesocket(WSOCKET s) as int
  101. ! WSACleanup () as int
  102. ! inet_addr (char *cp) as u_long 'cp: NULL-terminated character string representing a number expressed in the Internet standard ".'' (dotted) notation.
  103. ! htons(short hostshort) as short 'returns the value in TCP/IP network byte order
  104. ! connect(WSOCKET hSocket, sys *Name, int namelen) as int 'returns zero if no error
  105. ! send(WSOCKET s, char *buf, int len, int flags) as int
  106. ! recv(WSOCKET s, char *buf, int len, int flags) as int
  107. ! gethostbyname(char *name) as sys ' ptr to struct hostent
  108. ! inet_ntoa(in_addr in) as char ptr
  109.  
  110.  
  111. end extern
  112.  
  113.  
  114. sub main()
  115.  
  116.  
  117. WSADATA wsa
  118.  
  119. 'string host_name = "www.google.com" '216.58.209.100
  120. 'string host_name = "google.com" '173.194.112.228
  121. 'string host_name = "www.oxygenbasic.org" '12.158.189.153
  122. string host_name = "www.dict.org" '216.18.20.172
  123.  
  124. sys he 'hostent
  125.  
  126.  
  127. print cr & "Initialising Winsock..." & cr    
  128. if WSAStartup(0x0202, wsa) != 0 then    
  129.    print "Failed. Error Code : " WSAGetLastError() & cr        
  130.    return 1    
  131. end if        
  132.  
  133. print "Initialised." & cr  
  134.  
  135.     print "Calling gethostbyname with "  host_name & cr
  136.     he = gethostbyname( host_name )
  137. ' printl "he: " he & cr
  138.    if  he = NULL then    
  139.        //gethostbyname failed        
  140.        print "gethostbyname failed Error: "  WSAGetLastError() & cr        
  141.        exit sub  
  142.     end if
  143.  
  144.     hostent remoteHost at he
  145. /*
  146.     print "remotehost: "  @remoteHost & cr
  147.     print "remoteHost.h_name "  @remoteHost.h_name & cr
  148.     print "remoteHost.h_addrtype "  @remoteHost.h_addrtype & cr
  149.     print "remoteHost.h_length " @remoteHost.h_length & cr
  150.     print "remoteHost.h_addr_list " @remoteHost.h_addr_list & cr
  151.     print cr
  152. */    
  153.     print "Function returned:" & cr
  154.     print chr(9) & "Official name: "  remoteHost.h_name & cr
  155.  
  156.     print chr(9) & "Address type: "
  157.         select remoteHost.h_addrtype
  158.         case AF_INET:
  159.             print "AF_INET" & cr
  160.         case AF_NETBIOS:
  161.             print "AF_NETBIOS" & cr
  162.         case else
  163.             print remoteHost.h_addrtype & cr
  164.         end select
  165.        
  166.     print chr(9) & "Address length: " remoteHost.h_length & cr
  167.  
  168.     i = 1
  169.  
  170.     if remoteHost.h_addrtype = AF_INET then
  171.    
  172. ' print "remoteHost.h_addr_list: " @remoteHost.h_addr_list & cr    
  173.  
  174.     for x=1 to 3  
  175.       in_addr address at  @remoteHost.h_addr_list[x]
  176.       string ipA = inet_ntoa(address) : print x ": " ipA & cr
  177.     next x
  178.  
  179.  
  180.     end if      
  181.  
  182. end sub
  183.  
  184. main()
  185.  
  186. printl "enter ..." :waitkey()
  187.  

If there is no better solution I will use this code but I suppose I did something wrong.

Roland


.
« Last Edit: July 25, 2015, 02:57:29 AM by Arnold »

Charles Pegge

  • Guest
Re: Winsock functions with OxygenBasic
« Reply #3 on: July 20, 2015, 08:16:23 PM »

Hi Roland,

my cleanest solution:

simplify:

Code: OxygenBasic
  1. type hostent
  2.    char   *h_name
  3.    sys     h_aliases   'char**
  4.   short   h_addrtype
  5.    short   h_length
  6.    sys     h_addr_list 'char**
  7. end type
  8.  

then:

Code: OxygenBasic
  1.     sys *aa = remoteHost.h_aliases
  2.     sys *ad = remoteHost.h_addr_list
  3.     sys x
  4.     do
  5.       if ad then
  6.         x++
  7.         print x ": " inet_ntoa(byval *ad) & "  " (char)*aa  & cr
  8.         @aa+=sizeof sys
  9.         @ad+=sizeof sys
  10.       else
  11.         exit do
  12.       end if
  13.     end do
  14.  

complete code

Code: OxygenBasic
  1.  
  2. include "$/inc/console.inc"
  3.  
  4. /* Get IP address from domain name */
  5.  
  6. % SOCKET_ERROR          = -1
  7. % SOCK_STREAM           = 1
  8. % AF_INET               = 2
  9. % AF_NETBIOS            = 17
  10. % INVALID_SOCKET        = 0xFFFFFFFF
  11. % MSG_WAITALL           = 0x8
  12.  
  13. typedef sys WSOCKET
  14.  
  15.  
  16. type WSADATA 'Requires Windows Sockets 2.0
  17.  wVersion       as word          'WORD ( = 0x0202)                      
  18.  wHighVersion   as word          'WORD ( = 0x0202)                      
  19.  szDescription  as zString * 257 'char [WSADESCRIPTION_LEN+1]
  20.  szSystemStatus as zString * 129 'char [WSASYS_STATUS_LEN+1]  
  21.  iMaxSockets    as short         'unsigned short
  22.  iMaxUdpDg      as short         'unsigned short
  23.  lpVendorInfo   as Long          'char far*
  24. end type
  25.  
  26. /*
  27. typedef struct in_addr {
  28.   union {
  29.     struct {
  30.       u_char s_b1,s_b2,s_b3,s_b4;
  31.     } S_un_b;
  32.     struct {
  33.       u_short s_w1,s_w2;
  34.     } S_un_w;
  35.     u_long S_addr;
  36.   } S_un;
  37. } IN_ADDR, *PIN_ADDR, *LPIN_ADDR;
  38. */
  39.  
  40. 'type in_addr
  41.  union in_addr 's_un
  42.  {
  43.     type s_un_b
  44.     {
  45.       byte s_b1
  46.       byte s_b2
  47.       byte s_b3
  48.       byte s_b4
  49.     }
  50.     type s_un_w
  51.     {
  52.       short s_w1
  53.       short s_w2
  54.     }
  55.     sys s_addr
  56.   }
  57. 'end type
  58.  
  59. struct sockaddr {
  60.     short    sa_family    // address family, AF_xxx
  61.     char       sa_data[14]  // 14 bytes of protocol address}
  62. }
  63.  
  64.  
  65. // IPv4 AF_INET sockets:
  66. type sockaddr_in
  67.     sin_family as short   // e.g. AF_INET, AF_INET6
  68.     sin_port as short     // e.g. htons(3490)
  69.     sin_addr as in_addr   // see struct in_addr, below
  70.     sin_zero[8] as char   // zero this if you want to
  71. end type
  72.  
  73. /*
  74. typedef struct hostent {
  75.   char FAR      *h_name;
  76.   char FAR  FAR **h_aliases;
  77.   short         h_addrtype;
  78.   short         h_length;
  79.   char FAR  FAR **h_addr_list;
  80. } HOSTENT, *PHOSTENT, FAR *LPHOSTENT;
  81. */
  82.  
  83. 'type hostent
  84. '   char    *h_name
  85. '   sys     *h_aliases
  86. '   short   h_addrtype
  87. '   short   h_length
  88. '   in_addr *h_addr_list 'list of in_addr (s_addr is needed)
  89. 'end type
  90.  
  91. type hostent
  92.    char   *h_name
  93.    sys     h_aliases   'char**
  94.   short   h_addrtype
  95.    short   h_length
  96.    sys     h_addr_list 'char**
  97. end type
  98.  
  99. 'print "sizeof(hostent): " sizeof(hostent) & cr & cr
  100.  
  101. 'SELECTED PROCEDURES
  102. ====================
  103.  
  104. extern lib "ws2_32.dll"
  105.  
  106. ! WSAStartup (word wVersionRequested, WSADATA *lpWSAData) as int
  107. ! WSAGetLastError () as int
  108. ! socket(int af, int type, int protocol) as WSOCKET
  109. ! closesocket(WSOCKET s) as int
  110. ! WSACleanup () as int
  111. ! inet_addr (char *cp) as u_long 'cp: NULL-terminated character string representing a number expressed in the Internet standard ".'' (dotted) notation.
  112. ! htons(short hostshort) as short 'returns the value in TCP/IP network byte order
  113. ! connect(WSOCKET hSocket, sys *Name, int namelen) as int 'returns zero if no error
  114. ! send(WSOCKET s, char *buf, int len, int flags) as int
  115. ! recv(WSOCKET s, char *buf, int len, int flags) as int
  116. ! gethostbyname(char *name) as sys ' ptr to struct hostent
  117. ! inet_ntoa(in_addr in) as char ptr
  118.  
  119.  
  120. end extern
  121.  
  122.  
  123. sub main()
  124.  
  125.  
  126. WSADATA wsa
  127.  
  128. 'string host_name = "www.google.com" '216.58.209.100
  129. 'string host_name = "google.com" '173.194.112.228
  130. string host_name = "www.oxygenbasic.org" '12.158.189.153
  131. 'string host_name = "www.dict.org" '216.18.20.172
  132.  
  133. sys he 'hostent
  134.  
  135.  
  136. print cr & "Initialising Winsock..." & cr    
  137. if WSAStartup(0x0202, wsa) != 0 then    
  138.    print "Failed. Error Code : " WSAGetLastError() & cr        
  139.    return 1    
  140. end if        
  141.  
  142. print "Initialised." & cr  
  143.  
  144.     print "Calling gethostbyname with "  host_name & cr
  145.     he = gethostbyname( host_name )
  146. ' printl "he: " he & cr
  147.    if  he = NULL then    
  148.        //gethostbyname failed        
  149.        print "gethostbyname failed Error: "  WSAGetLastError() & cr        
  150.        exit sub  
  151.     end if
  152.  
  153.     hostent remoteHost at he
  154.     print "Function returned:" & cr
  155.     print chr(9) & "Official name: "  remoteHost.h_name & cr
  156.  
  157.     print chr(9) & "Address type: "
  158.         select remoteHost.h_addrtype
  159.         case AF_INET:
  160.             print "AF_INET" & cr
  161.         case AF_NETBIOS:
  162.             print "AF_NETBIOS" & cr
  163.         case else
  164.             print remoteHost.h_addrtype & cr
  165.         end select
  166.        
  167.     print chr(9) & "Address length: " remoteHost.h_length & cr
  168.  
  169.     if remoteHost.h_addrtype = AF_INET then
  170.    
  171.     sys *aa = remoteHost.h_aliases
  172.     sys *ad = remoteHost.h_addr_list
  173.     sys x
  174.     do
  175.       if ad then
  176.         x++
  177.         print x ": " inet_ntoa(byval *ad) & "  " (char)*aa  & cr
  178.         @aa+=sizeof sys
  179.         @ad+=sizeof sys
  180.       else
  181.         exit do
  182.       end if
  183.     end do
  184.  
  185.  
  186.     end if      
  187.  
  188. end sub
  189.  
  190. main()
  191.  
  192. printl "enter ..." :waitkey()
  193.  

Arnold

  • Guest
Re: Winsock functions with OxygenBasic
« Reply #4 on: July 21, 2015, 03:33:00 AM »
Hi Charles,

thank you once more for your help. The approach for accessing arrays from a pointer address will help me with further projects.

The aliases for the alternative names must be extracted seperately so I modified the code a little bit. Everything works fine now. There could be done much more with Winsock functions but this is all I will need for my little project. Nevertheless it is good to know that it would be possible to extend the winsock functionality if desired.

Roland

Code: OxygenBasic
  1. $ filename "GetHostByName.exe"
  2. 'include "$/inc/RTL32.inc"
  3.  
  4. include "$/inc/console.inc"
  5.  
  6. /* Get IP address from domain name */
  7.  
  8. % SOCKET_ERROR          = -1
  9. % SOCK_STREAM           = 1
  10. % AF_INET               = 2
  11. % AF_NETBIOS            = 17
  12. % INVALID_SOCKET        = 0xFFFFFFFF
  13. % MSG_WAITALL           = 0x8
  14.  
  15. typedef sys WSOCKET
  16.  
  17.  
  18. type WSADATA 'Requires Windows Sockets 2.0
  19.  wVersion       as word          'WORD ( = 0x0202)                      
  20.  wHighVersion   as word          'WORD ( = 0x0202)                      
  21.  szDescription  as zString * 257 'char [WSADESCRIPTION_LEN+1]
  22.  szSystemStatus as zString * 129 'char [WSASYS_STATUS_LEN+1]  
  23.  iMaxSockets    as short         'unsigned short
  24.  iMaxUdpDg      as short         'unsigned short
  25.  lpVendorInfo   as Long          'char far*
  26. end type
  27.  
  28.  
  29. 'type in_addr
  30.  union in_addr 's_un
  31.  {
  32.     type s_un_b
  33.     {
  34.       byte s_b1
  35.       byte s_b2
  36.       byte s_b3
  37.       byte s_b4
  38.     }
  39.     type s_un_w
  40.     {
  41.       short s_w1
  42.       short s_w2
  43.     }
  44.     sys s_addr
  45.   }
  46. 'end type
  47.  
  48. struct sockaddr {
  49.     short    sa_family    // address family, AF_xxx
  50.     char       sa_data[14]  // 14 bytes of protocol address}
  51. }
  52.  
  53.  
  54. // IPv4 AF_INET sockets:
  55. type sockaddr_in
  56.     sin_family as short   // e.g. AF_INET, AF_INET6
  57.     sin_port as short     // e.g. htons(80)
  58.     sin_addr as in_addr   // see struct in_addr, below
  59.     sin_zero[8] as char   // zero this if you want to
  60. end type
  61.  
  62.  
  63. type hostent
  64.    char   *h_name
  65.    sys     h_aliases   'char**
  66.   short   h_addrtype
  67.    short   h_length
  68.    sys     h_addr_list 'char**
  69. end type
  70.  
  71.  
  72. 'SELECTED PROCEDURES
  73. ====================
  74.  
  75. extern lib "ws2_32.dll"
  76.  
  77. ! WSAStartup (word wVersionRequested, WSADATA *lpWSAData) as int
  78. ! WSAGetLastError () as int
  79. ! socket(int af, int type, int protocol) as WSOCKET
  80. ! closesocket(WSOCKET s) as int
  81. ! WSACleanup () as int
  82. ! inet_addr (char *cp) as sys 'cp: NULL-terminated character string representing a number expressed in the Internet standard ".'' (dotted) notation.
  83. ! htons(short hostshort) as short 'returns the value in TCP/IP network byte order
  84. ! connect(WSOCKET hSocket, sys *Name, int namelen) as int 'returns zero if no error
  85. ! send(WSOCKET s, char *buf, int len, int flags) as int
  86. ! recv(WSOCKET s, char *buf, int len, int flags) as int
  87. ! gethostbyname(char *name) as sys  ' ptr to struct hostent
  88. ! inet_ntoa(in_addr in) as char ptr
  89.  
  90.  
  91. end extern
  92.  
  93.  
  94. sub main()
  95.  
  96.    WSADATA wsa
  97.  
  98.    'string host_name = "www.google.com" '216.58.209.100
  99.   'string host_name = "google.com" '173.194.112.228
  100.   'string host_name = "www.oxygenbasic.org" '12.158.189.153
  101.   'string host_name = "www.dict.org" '216.18.20.172
  102.   string host_name = "dict1.us.dict.org"  '216.18.20.172
  103.  
  104.     sys he 'hostent
  105.  
  106.     print cr & "Initialising Winsock..." & cr    
  107.     if WSAStartup(0x0202, wsa) != 0 then    
  108.        print "Failed. Error Code : " WSAGetLastError() & cr        
  109.        exit sub    
  110.     end if        
  111.  
  112.     print "Initialised." & cr  
  113.  
  114.     print "Calling gethostbyname with "  host_name & cr
  115.     he = gethostbyname( host_name )
  116.  
  117.     if  he = NULL then    
  118.        //gethostbyname failed        
  119.        print "gethostbyname failed Error: "  WSAGetLastError() & cr        
  120.        exit sub  
  121.     end if
  122.  
  123.     hostent remoteHost at he
  124.     print "Function returned:" & cr
  125.     print chr(9) & "Official name: "  remoteHost.h_name & cr
  126.  
  127.     sys *pAlias = remoteHost.h_aliases
  128.     sys x
  129.     do
  130.        if pAlias then
  131.           x++
  132.           print chr(9) & "Alternate name "x": " (char) *pAlias & cr
  133.           @pAlias+=sizeof sys  
  134.        else
  135.           exit do
  136.        end if
  137.     end do
  138.     print cr
  139.  
  140.     print chr(9) & "Address type: "
  141.     select remoteHost.h_addrtype
  142.         case AF_INET:
  143.             print "AF_INET" & cr
  144.         case AF_NETBIOS:
  145.             print "AF_NETBIOS" & cr
  146.         case else
  147.             print remoteHost.h_addrtype & cr
  148.     end select
  149.        
  150.     print chr(9) & "Address length: " remoteHost.h_length & cr
  151.  
  152.     if remoteHost.h_addrtype = AF_INET then  
  153.        sys *ad = remoteHost.h_addr_list
  154.        sys x
  155.        do
  156.          if ad then
  157.            x++
  158.            print x ": " inet_ntoa(byval *ad) & cr '"  " (char) *aa  & cr
  159.           @ad+=sizeof sys
  160.          else
  161.            exit do
  162.          end if
  163.        end do
  164.      end if      
  165.  
  166. end sub
  167.  
  168. main()
  169.  
  170. printl "Enter ..." :waitkey()
  171.  

.

Mike Lobanovsky

  • Guest
Re: Winsock functions with OxygenBasic
« Reply #5 on: July 21, 2015, 04:44:18 AM »
Quote
Code: OxygenBasic
  1. type WSADATA 'Requires Windows Sockets 2.0
  2.  .............................
  3.   szDescription  as zString * 257 'char [WSADESCRIPTION_LEN+1]
  4.  szSystemStatus as zString * 129 'char [WSASYS_STATUS_LEN+1]  
  5.  .............................
  6. end type

I believe that the individuals who venture to produce such weird alignments deserve public roasting on faggots.

(Charles, can you verify that a C++ compiler and OxygenBasic would generate structures with the exact same size, member offsets and lengths given the respective type defs?)

Charles Pegge

  • Guest
Re: Winsock functions with OxygenBasic
« Reply #6 on: July 21, 2015, 05:20:46 AM »
Yes, this structure requires no padding (or faggots!) since the alignment rules are satisfied for each member. 400 bytes total. Crafty devils.

Ha! I see 2 bytes padding is required before the last member lpVendorInfo, to bring it into dword alignment. And this would be extended to 6 in 64bit mode.
« Last Edit: July 21, 2015, 05:34:03 AM by Charles Pegge »

Mike Lobanovsky

  • Guest
Re: Winsock functions with OxygenBasic
« Reply #7 on: July 21, 2015, 06:36:42 AM »
The MSDN says the trailing member lpVendorInfo is ignored in winsock 2.0. I believe its deprecation might very well be due to its obvious misalignment and unusability. And it's also my sincere belief the author of this shitcode was sued to death by MS if not faggotted altogether.


JRS

  • Guest
Re: Winsock functions with OxygenBasic
« Reply #8 on: July 21, 2015, 03:35:57 PM »
Also why Microsoft's web server sucks. Bottom line, Windows is lucky to have the users they do have that were too lazy or committed to move on.
« Last Edit: July 21, 2015, 04:05:44 PM by John »

Arnold

  • Guest
Re: Winsock functions with OxygenBasic
« Reply #9 on: July 25, 2015, 03:05:38 AM »
Hi Charles,

this is a working version for connecting a client to a server, send and receive data. It runs on Windows Vista and Windows 7. Two months ago I would not have even tried to do this. And without the many resources available in Internet I would not have succeeded at all.

I would like to ask a question. To get the value of FIONBIO I simply copied the #define statements of Winsock2.h and changed u_long to unsigned long. I need FIONBIO for the ioctlsocket function. Setting the blocking mode on and off does work. This can be checked by changing the value of iMode in function receiveData. But is the value of FIONBIO correct (or is this not so important)? Could it be done with a macro?

Roland

Code: OxygenBasic
  1. 'Connect to a server, send and receive data
  2. 'the port and messages are specifically used for www.dict.org
  3.  
  4. $ filename "Dict_Send_Receive.exe"
  5. 'include "$/inc/RTL32.inc"
  6.  
  7. include "$/inc/console.inc"
  8.  
  9. % SOCKET_ERROR          = -1
  10. % SOCK_STREAM           = 1
  11. % AF_INET               = 2
  12. % INVALID_SOCKET        = 0xFFFFFFFF
  13. % INADDR_NONE           = 0xFFFFFFFF
  14. % WSAEWOULDBLOCK        = 10035
  15.  
  16.  
  17. type WSADATA 'Requires Windows Sockets 2.0
  18.  wVersion       as word          'WORD                      
  19.  wHighVersion   as word          'WORD                      
  20.  szDescription  as zString * 257 'char [WSADESCRIPTION_LEN+1]
  21.  szSystemStatus as zString * 129 'char [WSASYS_STATUS_LEN+1]  
  22.  iMaxSockets    as short         'unsigned short
  23.  iMaxUdpDg      as short         'unsigned short
  24.  lpVendorInfo   as Long          'char far*
  25. end type
  26.  
  27. 'in_addr structure
  28. type s_un_byte
  29.    s_b1 as byte
  30.    s_b2 as byte
  31.    s_b3 as byte
  32.    s_b4 as byte
  33. end type
  34. type s_un_word
  35.    s_w1 as short
  36.    s_w2 as short
  37. end type
  38.    
  39. type in_addr
  40.   union 's_un
  41.    s_un_b as s_un_byte
  42.     s_un_w as s_un_word
  43.     s_addr as sys
  44.   end union
  45. end type
  46.  
  47. type sockaddr
  48.     sa_family as short   ' address family, AF_xxx
  49.    sa_data[14] as char  ' 14 bytes of protocol address};
  50. end type
  51.  
  52. ' IPv4 AF_INET sockets:
  53. type sockaddr_in
  54.     sin_family as short   ' e.g. AF_INET, AF_INET6
  55.    sin_port as short     ' e.g. htons(80)
  56.    sin_addr as in_addr   ' see struct in_addr, below
  57.    sin_zero[8] as char   ' zero this if you want to
  58. end type
  59.  
  60. type hostent
  61.    char   *h_name
  62.    sys     h_aliases   'char**
  63.   short   h_addrtype
  64.    short   h_length
  65.    sys     h_addr_list 'char**
  66. end type
  67.  
  68. 'FIONBIO
  69. #define IOCPARM_MASK    0x7f     // Parameters must be < 128 bytes
  70. #define IOC_IN    0x80000000     // Copy in parameters
  71. #define _IOW(x,y,t)     (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y))
  72. #define FIONBIO _IOW('f', 126, unsigned long)
  73.  
  74.  
  75. 'SELECTED PROCEDURES
  76. ====================
  77.  
  78. extern lib "ws2_32.dll"
  79.  
  80. ! WSAStartup (word wVersionRequested, WSADATA *lpWSAData) as int
  81. ! WSAGetLastError () as int
  82. ! socket(int af, int type, int protocol) as sys
  83. ! closesocket(sys s) as int
  84. ! WSACleanup () as int
  85. ! inet_addr (char *cp) as long 'cp: NULL-terminated character string for a number using ".'' (dotted) notation.
  86. ! htons(short hostshort) as short 'returns the value in TCP/IP network byte order
  87. ! connect(sys hSocket, sys name, int namelen) as int 'returns zero if no error
  88. ! send(sys s, char *buf, int len, int flags) as int
  89. ! recv(sys s, char *buf, int len, int flags) as int
  90. ! gethostbyname(char *name) as sys  ' ptr to struct hostent
  91. ! inet_ntoa(in_addr in) as char *
  92. ! ioctlsocket(sys s, long cmd, sys *argp) as int
  93.  
  94. end extern
  95.  
  96. ! Sleep lib "kernel32.dll" (dword dwMilliseconds)
  97.  
  98. 'Helper functions
  99. =================
  100.  
  101. sub endSocket(sys skt)
  102.    closesocket(skt)
  103.    WSACleanup()
  104.    print "Socket closed" & cr      
  105. end sub
  106.  
  107. function findAddress(string host)
  108.    string ip_addr
  109.    sys pHE
  110.    
  111.    'try dotted IP address
  112.   sys address = inet_addr(host)
  113.    if address = INADDR_NONE then
  114.      'no dotted IP address, try DNS
  115.     print "Calling gethostbyname with "  host " waiting ..." & cr
  116.      pHE = gethostbyname(host)
  117.      if pHE = NULL then
  118.         print "gethostbyname failed Error: "  WSAGetLastError() & cr
  119.         return INADDR_NONE
  120.      end if
  121.      hostent remoteHost at pHE  
  122.      sys *ad = remoteHost.h_addr_list
  123.      'only try first address
  124.     if ad then
  125.        ip_addr = inet_ntoa(byval *ad)
  126.        address=inet_addr(ip_addr)
  127.        if address = INADDR_NONE then
  128.           print "gethostbyname failed Error: "  WSAGetLastError() & cr
  129.           return INADDR_NONE
  130.        end if      
  131.      else
  132.        print "failed ..."
  133.        return INADDR_NONE
  134.      end if
  135.    end if
  136.      
  137.    return address            
  138. end function
  139.  
  140. function connectHost(string host, int port)
  141.    WSADATA wsa
  142.    sockaddr_in server
  143.    
  144.    print cr & "Initialising Winsock..." & cr    
  145.    if WSAStartup(0x0202, wsa) != 0 then    
  146.       print "Initialising Socket failed. Error Code : " WSAGetLastError() & cr        
  147.       exit sub    
  148.    end if        
  149.  
  150.    print "Initialised." & cr
  151.  
  152.    ' Create a TCP socket
  153.   skt = socket(AF_INET , SOCK_STREAM , 0 )  
  154.  
  155.    if skt = INVALID_SOCKET then    
  156.       print "Could not create socket. Error: "   WSAGetLastError() & cr
  157.       exit sub    
  158.    end if    
  159.    print "Socket created." & cr
  160.    
  161.  
  162.    sys serv_address = findAddress(host)
  163.    server.sin_addr.s_addr = serv_address  
  164.    server.sin_family = AF_INET;    
  165.    server.sin_port = htons( port );
  166.  
  167.  
  168.    'Connect to remote server  
  169.   if connect(skt , &server , sizeof(sockaddr)) < 0 then  
  170.       print "Connect error" & cr
  171.       endSocket(skt)
  172.       skt=-1          
  173.    end if
  174.          
  175.    return skt
  176.  
  177. end function
  178.  
  179.  
  180. function sendData (sys s, string message)
  181.    string msg = message & chr(13) & chr(10)
  182.    
  183.    result = send(s , msg , len(msg) , 0)  
  184.    if result < 0 then
  185.       print "Send failed" & cr
  186.       endSocket(s)
  187.    end if              
  188.    return result
  189. end function
  190.  
  191. function receiveData(sys s) as string
  192.    string serv_reply=""
  193.    string buffer = ""
  194.    int length=1024
  195.    int recv_size
  196.    
  197.    unsigned long iMode=1 '0=blocking mode, 1=nonblocking mode
  198.   int iResult = ioctlsocket(s, FIONBIO, &iMode)
  199.    if iResult != 0 then
  200.      print "ioctlsocket failed with error: " iResult & cr
  201.      endSocket(s)
  202.      exit sub
  203.    end if
  204.    
  205.    while 1
  206.       serv_reply = nuls length  
  207.       recv_size = recv(s , serv_reply , length , 0)    
  208.  
  209.       if recv_size  = SOCKET_ERROR then
  210.          err = WSAGetLastError()
  211.          if err = WSAEWOULDBLOCK then Sleep(1000): continue while    
  212.          print "recv failed" & cr
  213.          serv_reply = "ERROR"
  214.          endSocket(s)          
  215.       else        
  216.          buffer &= left(serv_reply, recv_size)
  217.       end if
  218.       if recv_size < length then exit while
  219.    wend
  220.    
  221.    return buffer
  222. end sub
  223.  
  224.  
  225. sub main()
  226.  
  227.    sys skt
  228.    string s_reply
  229.  
  230.    string host_name = "www.dict.org" '216.18.20.172
  231.   'string host_name = "dict1.us.dict.org"  '216.18.20.172
  232.   'string host_name = "216.18.20.172"
  233.            
  234.    skt = connectHost(host_Name, 2628)
  235.    if skt < 0 then exit sub
  236.    print "Connected" & cr & cr
  237.  
  238.    'Send some data    
  239.   result = sendData(skt ,"SHOW DB")    
  240.    if result < 0 then exit sub            
  241.    print "Data Send (SHOW DB)" & cr
  242.  
  243.    'Receive a reply from the server
  244.   s_reply = receiveData(skt)
  245.    print s_reply
  246.    print cr  
  247.    
  248.    print "Send QUIT message" & cr
  249.  
  250.    result = sendData(skt , "QUIT")
  251.    if result < 0 then exit sub
  252.  
  253.    s_reply = receiveData(skt)
  254.    print s_reply
  255.    print cr
  256.  
  257.    'close
  258.   endSocket(skt)
  259.  
  260. end sub
  261.  
  262. main()
  263.  
  264. printl "Enter ..." : waitkey()
  265.  





[attachment deleted by admin]
« Last Edit: July 25, 2015, 03:30:22 AM by Arnold »

JRS

  • Guest
Re: Winsock functions with OxygenBasic
« Reply #10 on: July 25, 2015, 11:04:31 PM »
Glad to hear you got things working! Socket support on Windows seems to be an issue in every forum I visit.

Charles Pegge

  • Guest
Re: Winsock functions with OxygenBasic
« Reply #11 on: July 26, 2015, 01:07:41 AM »
Hi Roland,

That complicated macro seems to be correctly resolved, but It took some time for me to understand it :)

' FIONBIO 0x80000000 or (4<<16) or (102<<8 ) or 126

Thanks for all your work on this example.



Arnold

  • Guest
Re: Winsock functions with OxygenBasic
« Reply #12 on: July 26, 2015, 01:14:36 AM »
Hi John,

it was a great help to read your code of the thesaurus project which also pointed to www.dict.org and I found the link to the DICT protocol. So I could see what should happen. But I also noticed that using socket functions can be a very complicated topic. Some issues (like the WSADATA structure) seem to be vague.

I also found that I can create a running executable for 32 bit Windows, but when using RTL64.inc for a 64 bit Windows, the program runs but the send and recv functions fail. When searching in Internet I learned that there exist dlls like ws2_32.dll with the same names for 32 bit and 64 bit. Therefore I wonder if I mixed code for 32 and 64 bit by declaring the windows functions?

Roland

JRS

  • Guest
Re: Winsock functions with OxygenBasic
« Reply #13 on: July 26, 2015, 01:25:59 AM »
Roland,

I believe I had the Script BASIC version of the dictionary program running on Windows 64 bit. I use the cURL extension module if I need anything beyond basic socket support. SB native sockets doesn't have any timeout support and will hang the program.  :o

Arnold

  • Guest
Re: Winsock functions with OxygenBasic
« Reply #14 on: July 26, 2015, 02:59:47 AM »
Hi Charles,

for me it is amazing that by using:

#define FIONBIO   _IOW('f', 126, unsigned long)

Oxygenbasic does not get confused and does not see 'f' as a comment. This is only a little detail but it shows once more how well Oxygenbasic is elaborated.

Roland