Receiving and Sending Strings over the Network in QB64 - networking

I'm working on a mini pokemon game for my brother that works over the network.
Unfortunately, when testing I find that for some reason, it gives an error about "Bad file name or number" only on the lines where it tries to send a string to another computer, but has no error when looping the receive command.
Here's my code:
SCREEN 12
CLS
PRINT ""
PRINT ""
PRINT ""
PRINT ""
PRINT ""
PRINT " POKELITE - By Mark "
PRINT ""
PRINT ""
INPUT "Join or Host a game? ", hostorjoin$
hostorjoin$ = UCASE$(hostorjoin$)
IF hostorjoin$ = "JOIN" THEN GOTO JOIN
IF hostorjoin$ = "HOST" THEN GOTO HOST
HOST:
server& = _OPENHOST("TCP/IP:300")
PRINT "Waiting for connection..."
PRINT "! Remember: If playing locally, give the other player your IPv4 Address !"
DO
HOST& = _OPENCONNECTION(server&)
LOOP UNTIL HOST& <> 0
PRINT ""
PRINT "2nd Player Joined!"
SLEEP 2
GOTO GAME
JOIN:
INPUT "Enter Server IPv4 Address (Example: 192.168.1.25): ", joinip$
handle& = _OPENCLIENT("TCP/IP:300:" + joinip$)
IF handle& = 0 THEN PRINT "Connection failed!": SLEEP 2: CLS: GOTO JOIN
GOTO GAME
GAME:
CLS
INPUT "Enter your name: ", name$
IF name$ = "" THEN GOTO GAME
PRINT "Waiting for other player..."
IF hostorjoin$ = "JOIN" THEN
PUT HOST&, , name$
DO
GET handle&, , name2$
LOOP UNTIL name2$ <> ""
END IF
IF hostorjoin$ = "HOST" THEN
PUT handle&, , name$
DO
GET HOST&, , name2$
LOOP UNTIL name2$ <> ""
END IF
PRINT name$
PRINT name2$

You need to ensure the port is available, else server& will be an invalid server handle. Choosing a port of 49152 or higher is generally safe. This probably isn't your only problem, however.
Your problem is likely that your connection variable is simply not the same, meaning HOST& and handle& should just be handle&. It's important to remember that there is never a "host handle" and a "client handle"; the only handles are the "server handle" (created using _OPENHOST to essentially reserve a port for your connections) and the "connection handle" (created using _OPENCONNECTION by the server to connect to a client or _OPENCLIENT by the client to connect to a server). This will also reduce your logic to just do a PUT, followed by a GET loop. I use the name connection& instead of handle&, but you get the idea.
SCREEN 12
CLS
PRINT ""
PRINT ""
PRINT ""
PRINT ""
PRINT ""
PRINT " POKELITE - By Mark "
PRINT ""
PRINT ""
INPUT "Join or Host a game? ", hostorjoin$
hostorjoin$ = UCASE$(hostorjoin$)
IF hostorjoin$ = "JOIN" THEN GOTO JOIN
IF hostorjoin$ = "HOST" THEN GOTO HOST
' If neither "HOST" nor "JOIN" is specified, what happens?
HOST:
server& = _OPENHOST("TCP/IP:300")
PRINT "Waiting for connection..."
PRINT "! Remember: If playing locally, give the other player your IPv4 Address !"
DO
connection& = _OPENCONNECTION(server&)
LOOP UNTIL connection& <> 0
PRINT ""
PRINT "2nd Player Joined!"
SLEEP 2
GOTO GAME
JOIN:
INPUT "Enter Server IPv4 Address (Example: 192.168.1.25): ", joinip$
connection& = _OPENCLIENT("TCP/IP:300:" + joinip$)
IF connection& = 0 THEN PRINT "Connection failed!": SLEEP 2: CLS: GOTO JOIN
GOTO GAME
GAME:
CLS
INPUT "Enter your name: ", playerName$
IF playerName$ = "" THEN GOTO GAME
PRINT "Waiting for other player..."
' Send name to opponent and wait for opponent's name.
PUT connection&, , playerName$
DO
GET connection&, , opponentName$
LOOP UNTIL opponentName$ <> ""
PRINT "You: "; playerName$
PRINT "Opponent:"; opponentName$

Related

Why doesn't my pyserial port work in if-statement?

I can print the "reading" variable, but I can't figure out how to use it in an "if statement". As I said, it prints the string that I am sending from my microbit to my computer, but when I check if the string is == "A", it doesn't print "it works" EKS:
import keyboard
import serial.tools.list_ports
ports = serial.tools.list_ports.comports()
serialInst = serial.Serial()
portList = []
for onePort in ports:
portList.append(str(onePort))
print(str(onePort))
serialInst.baudrate = 115200
serialInst.port = "COM3"
serialInst.open()
while True:
if serialInst.in_waiting:
packet = serialInst.readline().decode('utf-8')
print(type(packet))
print(packet)
if packet == "A":
print("itworks")
#print(packet.decode('utf'))
if keyboard.is_pressed('esc'):
break
I found out:
You have to strip "packet"
So now it looks like this:
if packet.strip() == "A":
print("it works")

Additional prompt appearing after scp completes

after the scp completes in this code an additional prompt appears. I've tried several things to prevent this from happening, but it still appears. To be clear, two prompts appear after the for loop and then the program continues.
#!/usr/bin/expect
# Set timeout
set timeout 1
# Set the user and pass
set user "user"
set pass "pass"
# Get the lists of hosts, one per line
set f [open "hosts.txt"]
set hosts [split [read $f] "\n"]
close $f
# Get the commands to run, one per line
set f [open "commands.txt"]
set commands [split [read $f] "\n"]
close $f
# Clear console
set clear "clear"
# Iterate over the hosts
foreach host $hosts {
# Establish ssh conn
spawn ssh $user#$host
expect "password:"
send "$pass\r"
# Iterate over the commands
foreach cmd $commands {
expect "$ "
send "$cmd\r"
expect "password:"
send "$pass\r"
}
# Tidy up
# expect "$ "
# send "exit\r"
# expect eof
# send "close"
}
Because both your hosts and commands lists end with an empty string. Verify with puts [list $hosts $commands]
So you send an empty command, which is just "hitting enter". Then you wait for the password prompt, time-out in 1 second, and carry on with the program.
This is due to the way you're reading the files: read grabs the file contents, including the file's trailing newline. Then, when you split the string on newline, the list will include the empty string following the trailing newline.
Do this instead:
set commands [split [read -nonewline $f] "\n"]
# ........................^^^^^^^^^^
See https://tcl.tk/man/tcl8.6/TclCmd/read.htm
You could also do this
set f [open "commands.txt"]
while {[gets $f line] != -1} {
# skip empty lines and commented lines (optional)
if {[regexp {^\s*(#|$)} $line]} continue
lappend commands [string trim $line]
}
close $f

RDP session launch applications

I have opened an RDP session using AutoIt. Here is the code:
$host = "" ; <---- IP
$hGUI = GUICreate("Terminal Serveur", 952, 675, -1, -1, $WS_OVERLAPPEDWINDOW + $WS_CLIPSIBLINGS + $WS_CLIPCHILDREN)
$oRDP = ObjCreate("MsTscAx.MsTscAx.2")
$oRDP_Ctrl = GUICtrlCreateObj($oRDP, 64, 44, 800, 600)
GUICtrlSetResizing(-1, $GUI_DOCKALL)
GUICtrlSetStyle($oRDP_Ctrl , $WS_VISIBLE)
$oRDP.DesktopWidth = 800
$oRDP.DesktopHeight = 600
$oRDP.Fullscreen = False
$oRDP.ColorDepth = 16
$oRDP.AdvancedSettings3.SmartSizing = True
$oRDP.Server = $host
$oRDP.UserName = "" ; <--- Username
$oRDP.Domain = ""
$oRDP.AdvancedSettings2.ClearTextPassword = "" ; <--- Password
$oRDP.ConnectingText = "Connecting to " & $host
$oRDP.DisconnectedText = "Disconnected from " & $host
$oRDP.StartConnected = True
$oRDP.Connect()
$oShel = ObjCreate("shell.application")
$oShel_Ctrl = GUICtrlCreateObj($oShel, 64, 44, 800, 600)
GUICtrlSetStyle($oShel_Ctrl , $WS_VISIBLE)
GUISetState(#SW_SHOW, $hGUI)
Send ("#r") ; !!
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case $GUI_EVENT_CLOSE
$oRDP.Disconnect()
Exit
EndSwitch
WEnd
Now, I want to launch an application in the RDP session. I tried " Send(#r) " in order to send the path with a function like SendKeys but this command is execute on my computer and not on the remote computer.
How can I do please?
Send alt + home. This open the windows search in the rdp session, which you can then send it text e.g. send("notepad")
send({enter})
Update:
A much simpler alternative:
Change the Remote Desktop Connection Settings (not in the control
code, but in the usual windows shorcut. But it seems that could be done in the AutoIt code with the keyboardhook setting keyboardhook setting ) .
Look for the Options button, in the window when launching remote desktop.
On the Local Resources Tab select Windows key combinations are applied in full-screen mode only.
Change this line in your code:
$oRDP.Fullscreen = True
Include a pause to ensure the control has been loaded
Sleep(5000)
Send ("#r")
Previous answer:
Let my suggest a workaround not very 'elegant' but should work (tested ok):
In the remote desktop make a shorcut to the Windows Virtual Keyword (On-Screen Keyboard or OSK)
Find the position of the shorcut icon
In your code send a double click at this position to start the on-screen keyboard
Then send clicks to the positions of the desired keys
Something like this:
Sleep(5000)
MouseClick("left",512,191,2) ;start virtual keyword
Sleep(1000)
MouseClick("left",553,807,1) ;click
Sleep(100)
MouseClick("left",633,740,1)
Sleep(1000)
Send("notepad")
Sleep(1000)
Send("{ENTER}")
(Aside note: For any executable with a shortcut on the remote desktop simply send double click, without the need of the virtual keyboard)

Kicking clients from server (Erlang)

I'm new to Erlang and I am writing a basic server. I am trying to figure out how to correctly kick a client from the server using the information that I have about the client (which is Pid, Client_socket, and Client_name.
Any suggestions would be great and much appreciated. Thanks for reading :)
Here's my code so far:
-module(cell_clnt).
-export([cell_client/0]).
cell_client()->
%%% Add any needed parameters for your cell process here
Port = 21,
Pending_connections = 5,
Cell = fun()-> cell_process() end,
spawn(fun()-> timer:sleep(10), keyboard_loop(Cell) end),
receive
stop->
ok
end.
keyboard_loop(Cell)->
case io:get_line(">> ") of
"quit\n"->
io:fwrite("Exiting...~n"),
if is_pid(Cell)-> Cell!stop; true->ok end;
"start\n" when is_function(Cell)->
keyboard_loop(spawn(Cell));
Input when is_pid(Cell)->
Cell!{input,Input},
keyboard_loop(Cell);
_Input->
io:fwrite("No cell process active yet!~n"),
keyboard_loop(Cell)
end.
%%% Edit this to implement your cell process %%%
cell_process()->
io:fwrite("In cell~n"),
{ok,Listening_socket} = gen_tcp:listen(21,
[binary,
{backlog,5},
{active,false},
{packet,line}]),
loop(Listening_socket,[]).
loop(Listening_socket, Clients)->
io:format("Clients: ~p", [Clients]),
case gen_tcp:accept(Listening_socket) of
{ok,Client_socket} ->
gen_tcp:send(Client_socket, "Hello, what is your name?"),
{_,Name} = gen_tcp:recv(Client_socket,0),
gen_tcp:send(Client_socket, "Hello, "),
gen_tcp:send(Client_socket, Name),
Pid = spawn(fun()-> client_loop(Client_socket) end),
loop(Listening_socket,[{Pid,Client_socket,Name}|Clients])
end.
client_loop(Client_socket)->
case gen_tcp:recv(Client_socket,0) of
{ok,Message}-> gen_tcp:send(Client_socket,Message),
client_loop(Client_socket);
{error,Why}-> io:fwrite("Error: ~s~n",[Why]),
gen_tcp:close(Client_socket)
end.
Use when you need close a TCP socket and kill process:
gen_tcp:close(Socket)
exit(Pid, kill).
You can close a socket by killing the pid, like this:
erlang:exit(Pid, kill)

How to send an email containing greek characters using rJython?

The following function (found here) works well for messages containing ASCII characters. Can you help me modify it for multilingual messages too, because I don't know python at all?
send.email <- function(to, from, subject,
message, attachment=NULL,
username, password,
server="xxx.xxx.xxx.xxx",
confirmBeforeSend=FALSE){
# to: a list object of length 1. Using list("Recipient" = "recip#somewhere.net") will send the message to the address but
# the name will appear instead of the address.
# from: a list object of length 1. Same behavior as 'to'
# subject: Character(1) giving the subject line.
# message: Character(1) giving the body of the message
# attachment: Character(1) giving the location of the attachment
# username: character(1) giving the username. If missing and you are using Windows, R will prompt you for the username.
# password: character(1) giving the password. If missing and you are using Windows, R will prompt you for the password.
# server: character(1) giving the smtp server.
# confirmBeforeSend: Logical. If True, a dialog box appears seeking confirmation before sending the e-mail. This is to
# prevent me to send multiple updates to a collaborator while I am working interactively.
if (!is.list(to) | !is.list(from)) stop("'to' and 'from' must be lists")
if (length(from) > 1) stop("'from' must have length 1")
if (length(to) > 1) stop("'send.email' currently only supports one recipient e-mail address")
if (length(attachment) > 1) stop("'send.email' can currently send only one attachment")
if (length(message) > 1){
stop("'message' must be of length 1")
message <- paste(message, collapse="\\n\\n")
}
if (is.null(names(to))) names(to) <- to
if (is.null(names(from))) names(from) <- from
if (!is.null(attachment)) if (!file.exists(attachment)) stop(paste("'", attachment, "' does not exist!", sep=""))
if (missing(username)) username <- winDialogString("Please enter your e-mail username", "")
if (missing(password)) password <- winDialogString("Please enter your e-mail password", "")
require(rJython)
rJython <- rJython()
rJython$exec("import smtplib")
rJython$exec("import os")
rJython$exec("from email.MIMEMultipart import MIMEMultipart")
rJython$exec("from email.MIMEBase import MIMEBase")
rJython$exec("from email.MIMEText import MIMEText")
rJython$exec("from email.Utils import COMMASPACE, formatdate")
rJython$exec("from email import Encoders")
rJython$exec("import email.utils")
mail<-c(
#Email settings
paste("fromaddr = '", from, "'", sep=""),
paste("toaddrs = '", to, "'", sep=""),
"msg = MIMEMultipart()",
paste("msg.attach(MIMEText('", message, "'))", sep=""),
paste("msg['From'] = email.utils.formataddr(('", names(from), "', fromaddr))", sep=""),
paste("msg['To'] = email.utils.formataddr(('", names(to), "', toaddrs))", sep=""),
paste("msg['Subject'] = '", subject, "'", sep=""))
if (!is.null(attachment)){
mail <- c(mail,
paste("f = '", attachment, "'", sep=""),
"part=MIMEBase('application', 'octet-stream')",
"part.set_payload(open(f, 'rb').read())",
"Encoders.encode_base64(part)",
"part.add_header('Content-Disposition', 'attachment; filename=\"%s\"' % os.path.basename(f))",
"msg.attach(part)")
}
#SMTP server credentials
mail <- c(mail,
paste("username = '", username, "'", sep=""),
paste("password = '", password, "'", sep=""),
#Set SMTP server and send email, e.g., google mail SMTP server
paste("server = smtplib.SMTP('", server, "')", sep=""),
"server.ehlo()",
"server.starttls()",
"server.ehlo()",
"server.login(username,password)",
"server.sendmail(fromaddr, toaddrs, msg.as_string())",
"server.quit()")
message.details <-
paste("To: ", names(to), " (", unlist(to), ")", "\n",
"From: ", names(from), " (", unlist(from), ")", "\n",
"Using server: ", server, "\n",
"Subject: ", subject, "\n",
"With Attachments: ", attachment, "\n",
"And the message:\n", message, "\n", sep="")
if (confirmBeforeSend)
SEND <- winDialog("yesnocancel", paste("Are you sure you want to send this e-mail to ", unlist(to), "?", sep=""))
else SEND <- "YES"
if (SEND %in% "YES"){
jython.exec(rJython,mail)
cat(message.details)
}
else cat("E-mail Delivery was Canceled by the User")
}
I call it like this:
send.email(list("somebody#somecompany.com"),
list("rJythonMail#mycompany.com"),
"Δοκιμή αποστολής email με attachment",
"Με χρήση της rJython",
attachment="monthly_report.xls",
username="gd047",password="xxxxxx")
The issue is how your enclosed Python code is structured. This blog entry goes into more detail on how to properly send Unicode email, which you're using Python to manage the underling SMTP connection for. Note that according to R. David Murray, this will be fixed in later iterations of the email package in Python.
Here's the salient Python code you can retrofit into your calls in rJython, borrowing directly from the aforementioned blog post:
from smtplib import SMTP
from email.MIMEText import MIMEText
from email.Header import Header
from email.Utils import parseaddr, formataddr
def send_email(sender, recipient, subject, body):
"""Send an email.
All arguments should be Unicode strings (plain ASCII works as well).
Only the real name part of sender and recipient addresses may contain
non-ASCII characters.
The email will be properly MIME encoded and delivered though SMTP to
localhost port 25. This is easy to change if you want something different.
The charset of the email will be the first one out of US-ASCII, ISO-8859-1
and UTF-8 that can represent all the characters occurring in the email.
"""
# Header class is smart enough to try US-ASCII, then the charset we
# provide, then fall back to UTF-8.
header_charset = 'ISO-8859-1'
# We must choose the body charset manually
for body_charset in 'US-ASCII', 'ISO-8859-1', 'UTF-8':
try:
body.encode(body_charset)
except UnicodeError:
pass
else:
break
# Split real name (which is optional) and email address parts
sender_name, sender_addr = parseaddr(sender)
recipient_name, recipient_addr = parseaddr(recipient)
# We must always pass Unicode strings to Header, otherwise it will
# use RFC 2047 encoding even on plain ASCII strings.
sender_name = str(Header(unicode(sender_name), header_charset))
recipient_name = str(Header(unicode(recipient_name), header_charset))
# Make sure email addresses do not contain non-ASCII characters
sender_addr = sender_addr.encode('ascii')
recipient_addr = recipient_addr.encode('ascii')
# Create the message ('plain' stands for Content-Type: text/plain)
msg = MIMEText(body.encode(body_charset), 'plain', body_charset)
msg['From'] = formataddr((sender_name, sender_addr))
msg['To'] = formataddr((recipient_name, recipient_addr))
msg['Subject'] = Header(unicode(subject), header_charset)
# Send the message via SMTP to localhost:25
smtp = SMTP("localhost")
smtp.sendmail(sender, recipient, msg.as_string())
smtp.quit()
Once ported, this should get your code working. Hopefully, better support for RFC2047 and RFC3490 will be added soon. For now, you regrettably have to hack around the issue.

Resources