BBC BASIC for Windows
Programming >> Communication and Input/Output >> Sockets
http://bb4w.conforums.com/index.cgi?board=communication&action=display&num=1512576948

Sockets
Post by KenDown on Dec 6th, 2017, 3:15pm

What I want to do is send a key-press from my programming running on one computer to a similar program running on another computer. Back in the days when Richard was still here he suggested that I needed to learn socket programming and I've finally got around to trying out his advice.

I use PROC_initialisesockets on both computers then FN_tcpconnect on the sending computer and FN_tcplisten on the receiving one followed by FN_check_connection. I set up a buffer on both and then use FN_writelinesocket on the sender and FN_readsocket on the receiver.

Not knowing any better, I'm using port 25 on both.

The sender says that everything is fine and does what it is supposed to do; the receiver can't get past FN_check_connection.

Any advice would be gratefully received.
Re: Sockets
Post by DDRM on Dec 11th, 2017, 08:01am

Hi Kendall,

I'm not ignoring you, but I haven't answered because I can't make it work! Possibly because I was trying on a computer which is working through a proxy server and my laptop, connected to a separate wireless network.

Could you post your basic code as a starting point? Obviously replace all explicit machine names/IP addresses with placeholders.

The only thing I can suggest offhand is using port 23 (Telnet) or 80 (HTTP) instead of port 25 (SMTP). FTP is port 21, which might also be worth a go.

Best wishes,

D
Re: Sockets
Post by KenDown on Dec 11th, 2017, 2:52pm

That's very kind of you. Here are the two programs.

REM Program to send a message via socket programming
REM Alter the variable query$ in PROCfindname to the network
REM name of the receiving computer

INSTALL@lib$+"SOCKLIB"
PROC_initsockets
host$=FN_gethostname
PRINThost$
hostent%=FN_sethost(host$)
hostip%=!!hostent%!12
PRINTFNipaddrs(hostip%)

PROCfindname

REPEAT
socnum%=FN_tcpconnect(dest$,"25")
UNTILsocnum%>0
PRINT"Peer name: "FN_getpeername(socnum%)

PRINT"Connection established: "socnum%

DIMbuffer%256
?buffer%=7

try%=0
REPEAT
success%=FN_writesocket(socnum%,buffer%,1)
PRINTsuccess%
try%+=1
UNTILtry%=10

try%=0
REPEAT
success%=FN_writelinesocket(socnum%,CHR$7)
PRINTsuccess%
try%+=1
UNTILtry%=10


PROC_exitsockets
END
:
DEFFNipaddrs(addr%)
=STR$(addr%AND255)+"."+STR$(addr%>>>8AND255)+"."+STR$(addr%>>>16AND255)+"."+STR$(addr%>>>24AND255)
:
DEFPROCfindname
SYS"LoadLibrary","dnsapi.dll"TOdnsapi%
SYS"GetProcAddress",dnsapi%,"DnsQuery_A"TO`DnsQuery`
SYS"GetProcAddress",dnsapi%,"DnsRecordListFree"TO`DnsRecordListFree`

DIMdnsr{pNext%,pName%,wType{l&,h&},wDataLength{l&,h&},dwFlags%,dwTtl%,dwReserved%,dwData%}

query$="Computer2"

SYS`DnsQuery`,query$,1,1,0,dnsr{},0
rr%=dnsr.pNext%

WHILEdnsr.pNext%
!(^dnsr{}+4)=dnsr.pNext%
PRINT$$dnsr.pName% " ",FNipaddrs(dnsr.dwData%)
ENDWHILE
dest$=FNipaddrs(dnsr.dwData%)
SYS`DnsRecordListFree`,rr%,0
SYS"FreeLibrary",dnsapi%
ENDPROC


==================

REM Program to receive a message via socket programming
REM Alter the variable query$ in PROCfindname to the network
REM name of the sending computer

INSTALL@lib$+"SOCKLIB"
PROC_initsockets
host$=FN_gethostname
PRINThost$
hostent%=FN_sethost(host$)
hostip%=!!hostent%!12
PRINTFNipaddrs(hostip%)

PROCfindname


PRINT"Checking connection"
REPEAT
socnum%=FN_tcplisten(host$,"25")
UNTILsocnum%>0

PRINT"Connection established"
REPEAT
success%=FN_check_connection(socnum%)
PRINTFN_getpeername(success%)
g%=INKEY(10)
UNTILsuccess%>0ORg%=13

PRINTsuccess%" Connection checked"

DIMbuffer%256

REPEAT
inbyte%=FN_readsocket(success%,buffer%,1)
PRINTinbyte%
g%=INKEY(2)
UNTILinbyte%>0ORg%=13

VDU?buffer%

PROC_exitsockets
END
:
DEFFNipaddrs(addr%)
=STR$(addr%AND255)+"."+STR$(addr%>>>8AND255)+"."+STR$(addr%>>>16AND255)+"."+STR$(addr%>>>24AND255)
:
DEFPROCfindname
SYS"LoadLibrary","dnsapi.dll"TOdnsapi%
SYS"GetProcAddress",dnsapi%,"DnsQuery_A"TO`DnsQuery`
SYS"GetProcAddress",dnsapi%,"DnsRecordListFree"TO`DnsRecordListFree`

DIMdnsr{pNext%,pName%,wType{l&,h&},wDataLength{l&,h&},dwFlags%,dwTtl%,dwReserved%,dwData%}

query$="Computer1"

SYS`DnsQuery`,query$,1,1,0,dnsr{},0
rr%=dnsr.pNext%

WHILEdnsr.pNext%
!(^dnsr{}+4)=dnsr.pNext%
PRINT$$dnsr.pName% " ",FNipaddrs(dnsr.dwData%)
ENDWHILE
dest$=FNipaddrs(dnsr.dwData%)
SYS`DnsRecordListFree`,rr%,0
SYS"FreeLibrary",dnsapi%
ENDPROC


Provided a valid network name is put in the sending program it will return values showing that the messages have been sent successfully.

Even with a valid network name in the receiving program, it hangs at the point of checking the connection.
Re: Sockets
Post by sveinioslo on Dec 17th, 2017, 08:58am

Hi.

Made the necessary changes to your programs.
It's easier if you send something printable.
Notice the difference on the receiver end when you send at full speed.(REMout WAIT 25)
If you use the ide's close button to stop your program, then you will need to close and reopen the ide.
Your program is likely to fail otherwise. Socklib is VERY sensitive to proper handling.
Watch out for windows firewall and other security software, they might interfere.
Have not checked the dns part.

Svein


The sender.
Code:
      INSTALL@lib$+"SOCKLIB"
      PROC_initsockets
      host$=FN_gethostname
      PRINThost$
      hostent%=FN_sethost(host$)
      hostip%=!!hostent%!12
      PRINTFNipaddrs(hostip%)

      ON CLOSE PROC_exitsockets : QUIT         : REM important
      ON ERROR PROC_exitsockets : REPORT : END : REM important

      PROCfindname

      dest$=host$   : REM if testing locally
      REPEAT
        socnum%=FN_tcpconnect(dest$,"12325")
      UNTILsocnum%>0
      PRINT"Peer name: "FN_getpeername(socnum%)

      PRINT"Connection established: "socnum%

      DIMbuffer%255
      PRINT "Sending bytes"
      try%=0
      REPEAT
        ?buffer%=48+try%     : REM Printable bytes
        PRINT try% : WAIT 25 : REM
        success%=FN_writesocket(socnum%,buffer%,1)
        try%+=1
      UNTILtry%=10
      success%=FN_writelinesocket(socnum%,"") : REM newline

      PRINT "Sending lines"
      try%=0
      REPEAT
        PRINT try% : WAIT 25 : REM
        success%=FN_writelinesocket(socnum%,"Hello"+STR$(try%))
        try%+=1
      UNTILtry%=10
      PROC_closesocket(socnum%) : REM close before exit

      PRINT "Finished"
      PROC_exitsockets
      END
      :
      DEFFNipaddrs(addr%)
      =STR$(addr%AND255)+"."+STR$(addr%>>>8AND255)+"."+STR$(addr%>>>16AND255)+"."+STR$(addr%>>>24AND255)
      :
      DEFPROCfindname
      SYS"LoadLibrary","dnsapi.dll"TOdnsapi%
      SYS"GetProcAddress",dnsapi%,"DnsQuery_A"TO`DnsQuery`
      SYS"GetProcAddress",dnsapi%,"DnsRecordListFree"TO`DnsRecordListFree`

      DIMdnsr{pNext%,pName%,wType{l&,h&},wDataLength{l&,h&},dwFlags%,dwTtl%,dwReserved%,dwData%}

      query$="Computer2"

      SYS`DnsQuery`,query$,1,1,0,dnsr{},0
      rr%=dnsr.pNext%

      WHILEdnsr.pNext%
        !(^dnsr{}+4)=dnsr.pNext%
        PRINT$$dnsr.pName% " ",FNipaddrs(dnsr.dwData%)
      ENDWHILE
      dest$=FNipaddrs(dnsr.dwData%)
      SYS`DnsRecordListFree`,rr%,0
      SYS"FreeLibrary",dnsapi%
      ENDPROC
 


The receiver.
Code:
      INSTALL@lib$+"SOCKLIB"
      PROC_initsockets
      host$=FN_gethostname
      PRINThost$
      hostent%=FN_sethost(host$)
      hostip%=!!hostent%!12
      PRINTFNipaddrs(hostip%)

      ON CLOSE PROC_exitsockets : QUIT         : REM important
      ON ERROR PROC_exitsockets : REPORT : END : REM important

      PROCfindname

      PRINT"Checking connection"
      REPEAT
        socnum%=FN_tcplisten(host$,"12325")
        IF socnum%<0 THEN PRINT FN_socketerror
      UNTILsocnum%>0

      PRINT"Listening"
      REPEAT
        success%=FN_check_connection(socnum%)
        WAIT 0
      UNTILsuccess%>0

      PRINT "Connected to "FN_getpeername(success%)

      REM buffer content need to be parsed
      DIMbuffer%255
      REPEAT
        inbyte%=FN_readsocket(success%,buffer%,255)
        IF inbyte%>0 THEN
          PRINT "Received ";inbyte%;" bytes"
          FOR I%=0 TO inbyte%-1
            PRINT CHR$buffer%?I%;
          NEXT
        ELSE
          WAIT 0
        ENDIF
      UNTIL inbyte%=-1

      PRINT "Disconnected"
      PROC_exitsockets
      END
      :
      DEFFNipaddrs(addr%)
      =STR$(addr%AND255)+"."+STR$(addr%>>>8AND255)+"."+STR$(addr%>>>16AND255)+"."+STR$(addr%>>>24AND255)
      :
      DEFPROCfindname
      SYS"LoadLibrary","dnsapi.dll"TOdnsapi%
      SYS"GetProcAddress",dnsapi%,"DnsQuery_A"TO`DnsQuery`
      SYS"GetProcAddress",dnsapi%,"DnsRecordListFree"TO`DnsRecordListFree`

      DIMdnsr{pNext%,pName%,wType{l&,h&},wDataLength{l&,h&},dwFlags%,dwTtl%,dwReserved%,dwData%}

      query$="Computer1"

      SYS`DnsQuery`,query$,1,1,0,dnsr{},0
      rr%=dnsr.pNext%

      WHILEdnsr.pNext%
        !(^dnsr{}+4)=dnsr.pNext%
        PRINT$$dnsr.pName% " ",FNipaddrs(dnsr.dwData%)
      ENDWHILE
      dest$=FNipaddrs(dnsr.dwData%)
      SYS`DnsRecordListFree`,rr%,0
      SYS"FreeLibrary",dnsapi%
      ENDPROC
 


Re: Sockets
Post by KenDown on Dec 17th, 2017, 1:43pm

Thanks. I'm going to have to study this, so please excuse the lack of an immediate full reply.
Re: Sockets
Post by DDRM on Dec 18th, 2017, 10:24am

Thanks, Svein.

I've been busy and unwell, so I haven't had a chance to look at either Kendall's programmes or your modified version.

Best wishes,

D