I'm trying to make client-server connection, I don't know much about sockets etc. so I used github example for luajitsocket and im getting error "A non-blocking socket operation could not be completed immediately."
So I dont even know how can I fix that, that's why Im asking here
My code:
local port = 8080
local address = socket.find_first_address("*", port)
do -- server
local server = assert(socket.create("inet", "dgram", "udp"))
assert(server:set_blocking(false))
assert(server:bind(address))
print("hosting at ", address:get_ip(), address:get_port())
function update_server()
local data, addr = server:receive_from()
if data then
print(data)
assert(server:send_to(addr, "hello from server " .. os.clock()))
elseif addr ~= "timeout" then
error(addr)-- here
end
end
end
do -- client
local client = assert(socket.create("inet", "dgram", "udp"))
assert(client:set_blocking(false))
local next_send = 0
function update_client()
if next_send < os.clock() then
assert(client:send_to(address, "hello from client " .. os.clock()))
next_send = os.clock() + math.random() + 0.5
end
local data, addr = client:receive_from(address)
if data then
print(data, addr:get_ip(), addr:get_port())
elseif addr ~= "timeout" then
error(addr)
end
end
end
while true do
update_server()
update_client()
end
taken from: https://github.com/CapsAdmin/luajitsocket/blob/master/examples/udp_client_server.lua
I was looking about this error on google but can't find any working solution. Thanks in advance!
After set_blocking(false) that return code should not be considered abnormal.
You're probably getting it from receive_from(), which you should not be calling constantly, you should do it when select() or poll() tells you the socket has data waiting.
Related
I'm trying to make a serial communication between two ESP8266 Wifi chips.
To start, I tried sending a sample data 10 times in a for loop. Here is the code:
Transmiter:
for Packets = 1 : 10
SendData(client,Data(Packets));
end
Receiver:
Packets = 1
while(1)
Data(Packets) = ReceiveData(Server);
Packets = Packets + 1;
if (packets == 10)
break
end
end
it works good. The problem is when I want to send data with some delays, the transmitter should connect to receiver again and the server (receiver) receives some data indicating that connection is made again.
The received Buffer should be:
+IPD,0,1024:ùüþþþýýþþÿÿûûýþýûúþÿúóýÿþþþþþýúøûýþ...
but after reconnecting the received Buffer is:
0,CLOSED %Receiver Prompt, disconnected from Transmiter
0,CONNECT %Receiver Prompt,connected to Transmiter
+IPD,0,1024:ùüþþþýýþþÿÿûûýþýûúþÿúóýÿþþþþþýúøûýþ...
The remaining part of data will be read in next packet and same for next packets.
what should I do to receive just the data?
The send and receive functions:
function ReceivedBuffer = ReceiveData(SerialPort)
ReceivedBuffer = fread(server,1038); %Size data = 1038 Bytes
end
function SendData(SerialPort,Data)
fwrite(SerialPort,Data);
end
I am working on making an interface between MATLAB and Arduino. In other words, I want to send some data from MATLAB to Arduino. I have written programs both in MATLAB and the Arduino IDE.
MATLAB program:
c = 1;
if (c ~= 0 )
f = 1;
else
disp('vhxhjf');
end
disp(f)
arduino=serial('COM5','BaudRate',9600); % create serial communication object on port COM4
fopen(arduino); % initiate arduino communication
while f
fprintf(arduino,'%s',char(f)); % send answer variable content to arduino
end
fclose(arduino); % end communication with arduino
Code for Arduino:
int ledPin = 13;
int matlabData ;
void setup() {
pinMode(13,OUTPUT);
Serial.begin(9600);
// turn the LED on when we're done
// digitalWrite(13, HIGH);
}
void loop() {
if(Serial.available() > 0 ) {
matlabData = Serial.read();
if ( matlabData != 0) {
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13,LOW);
delay(1000);
}
else
digitalWrite(13,LOW);
}
}
The problem is whenever I am uploading the sketch , this error is being thrown regularly in arduino ide:
avrdude: ser_open(): can't open device "\\.\COM5": The system cannot find the file specified
It was works on the first try, but after that the above error is thrown continuosly .
Also in matlab, after the first try , the following error is thrown:
enter code here
Error using serial/fopen (line 72)
Open failed: Port: COM5 is not available. No ports are available.
Use INSTRFIND to determine if other instrument objects are connected to requested device.
Error in SP (line 65)
fopen(arduino); % initiate arduino communication
>> instrfind
Instrument Object Array
Index: Type: Status: Name:
1 serial open Serial-COM5
2 serial closed Serial-COM5
and also the command instrfind is showing that the com5 port is closed after the first try.
I have tried the solution given in this link but it is didn't work:
http://forum.arduino.cc/index.php?topic=48421.0
This usually happens when you don't close the port.
In your code, when do you close it? When is f changed so the loop exits?
According to these people, you can try to do
delete(instrfindall)
before trying to open the port or
fopen(arduino);
closeFID = onCleanup(#() fclose(arduino));
...
IMHO the second solution looks better (less destructive)
BTW: put a delay or a sleep (I don't know how this is done in ML) in the fprintf loop, otherwise you will send too many data to the poor Arduino...
I have an application which listens to multiple connections and verifies whether the user is active or not
I use a 1 thread socket handling method with WSAASyncSelect.
The problem is that sometimes when a lot of users connecting at the same time some users get no reply
i think it is because the "send" hasn't been called yet and the program has received another connection so it goes again to handle the new connection ignoring the previous one. Like WSAASyncSelect has triggered and now it processing a new connection instead of completing the previous request.
So what to do to fix this issue? i tried to stop the events from WSAASyncSelect temporary by calling it with zero parameters when handling the connection until finish it then re enable network events but that didn't help either.
Here are the codes that handling the events (recieve then decrypt and then compare the bytes then send data according to what in listbox ie Active user or not)
This called upon receive of FD_READ
WSAAsyncSelect s, frmMain.hwnd, 0, 0 'Disabling Notifications event
Do Until bytesRecieved = SOCKET_ERROR
bytesRecieved = recv(wParam, buffer(Bytes), 500, 0)
If bytesRecieved > 0 Then
Bytes = Bytes + bytesRecieved
ElseIf bytesRecieved = 0 Then
Exit Sub
End If
Loop
Call MemCopy(ByVal decryptedArrival, buffer(0), Bytes)
WSAAsyncSelect s, frmMain.hwnd, WINSOCKMSG, FD_CONNECT + FD_READ + FD_CLOSE + FD_ACCEPT + FD_WRITE
If frmMain.chkSaveLog.value = vbChecked Then
frmMain.txtConnectionsLog.Text = frmMain.txtConnectionsLog.Text & Now & " Receiving a connection (" & wParam & ")" & vbNewLine
AutoScroll
If frmMain.chkAutoSave.value = vbChecked Then
strCurrentLogLine = Now & " Receiving a connection (" & wParam & ")"
AutoSaveLog (strCurrentLogLine)
frmMain.cmdClearLogs.Enabled = True
End If
End If
Below here is a decryption of bytes then comparing by ID as byte identifier like 1 = check for update
2 - send user info etc
in a Select Case statement following by a send Api.
And the accepting procedure
This called upon receive of FD_ACCEPT
Function AcceptConnection(wParam As Long)
lpString = String(32, 0)
AcSock = accept(wParam, sockaddress, Len(sockaddress))
strTempIP = getascip(sockaddress.sin_addr)
frmMain.txtConnectionsLog.Text = frmMain.txtConnectionsLog.Text & Now & " Getting a connection from IP address: " & _
strTempIP & " (" & AcSock & ")" & vbNewLine
AutoScroll
If frmMain.chkAutoSave.value = vbChecked Then
strCurrentLogLine = Now & " Getting a connection from IP address: " & strTempIP & " (" & AcSock & ")" & vbNewLine
AutoSaveLog (strCurrentLogLine)
End If
End Function
Are there any suggestions for a better performance?
What you showed is NOT the correct way to use WSAAsyncSelect(). Try something more like this instead:
When creating a listening socket:
lSock = socket(...)
bind(lSock, ...)
listen(lSock, ...)
WSAAsyncSelect lSock, frmMain.hwnd, WINSOCKMSG, FD_ACCEPT
When a listening socket receives FD_ACCEPT:
Function AcceptConnection(wParam As Long)
AcSock = accept(wParam, sockaddress, Len(sockaddress))
If AcSock = INVALID_SOCKET Then
Exit Sub
End If
WSAAsyncSelect AcSock, frmMain.hwnd, WINSOCKMSG, FD_READ + FD_CLOSE + FD_WRITE
...
End Function
When an accepted client socket receives FD_READ:
Function ReadConnection(wParam As Long)
Do
bytesRecieved = recv(wParam, ReadBuffer(ReadBytes), 500, 0)
If bytesRecieved = SOCKET_ERROR Then
If WSAGetLastError() <> WSAEWOULDBLOCK Then
Exit Sub
End If
ElseIf bytesRecieved = 0 Then
Exit Sub
Else
ReadBytes = ReadBytes + bytesRecieved
End If
Loop Until bytesRecieved = SOCKET_ERROR
' process ReadBuffer up to ReadBytes number of bytes as needed...
' remove processed bytes from front of ReadBuffer and decrement ReadBytes accordingly
...
End Function
When an accepted client socket receives FD_WRITE:
Function WriteConnection(wParam As Long)
While SendBytes > 0
bytesSent = send(wParam, SendBuffer(0), SendBytes, 0)
If bytesSent = SOCKET_ERROR Then
Exit Sub
End If
' remove bytesSent number of bytes from front of SendBuffer ...
SendBytes = SendBytes - bytesSent;
End While
End Function
The trick is that you need to allocate separate ReadBuffer and SendBuffer buffers for each accepted client. Make sure that each time you receive FD_READ that you are appending bytes only to the ReadBuffer of the socket that triggered FD_READ, and each time you receive FD_WRITE that you are removing bytes only from the SendBuffer of the socket that triggered FD_WRITE.
When recv() has no more bytes to read, process that socket's ReadBuffer as needed, removing only complete messages from the front and leaving incomplete messages for later processing.
When send() fails with WSAEWOULDBLOCK, append any unsent bytes to the SendBuffer of the socket that caused send() to fail. When you receive an FD_WRITE event for a socket, check that socket's SenBuffer and resend any bytes that are in it, stopping when the buffer is exhausted or an WSAEWOULDBLOCK error occurs.
Very easy, and quite effective, way to do it is to fork out for every incoming connection. This will most likely require you to restructure your application, but the basic flow should be as follows:
1. New connection is opened to the server
2. Server accepts the connection and forks out
3. The fork closes the original socket for listening, so only the parent will be accepting new connections
4. And then your magic happens, separate from the original thread.
This way you do not have to worry about issues of concurrency, as long as your machine can handle all the traffic and load because each connections is independent.
EDIT: I solved this question myself, look at the first answer if you have a similar issue
I am new to sockets and made a client-server test modifying one example, it sends and receives data ok but when closing the server get caught in a loop receiving blank messages and I can't find out why even though I use shutdown(socket.SHUT_RDWR) to close the connection immediately according to the documentation.
I had to use two cmd of windows for each one (server and client) because when running first the server in idle and then the client I got in client_example ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it here is the code. Anyways, here it is the sequence I tried:
(in the client console):
c:\python33\python client_example.py
SEND( TYPE q or Q to Quit):Hi
SEND( TYPE q or Q to Quit):q
(in the server console):
c:\python33\python server_example3.py
TCPServer Waiting for client on port 7000
I got a connection from ('127.0.0.1', 49263)
RECEIVED: b'Hi'
RECEIVED: b''
RECEIVED: b''
RECEIVED: b''
RECEIVED: b''
RECEIVED: b''
.... <---After I did CTRL+C
Traceback (most recent call last):
File "server_example.py", line 19, in <module>
print("RECEIVED:",data)
File "c:\python33\lib\encodings\cp850.py", line 19, in encode
return codecs.charmap_encode(input,self.errors,encoding_map)[0]
KeyboardInterrupt
Here is the code of the server and client:
server_example.py:
#TCP server example
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(("", 7000))
server_socket.listen(5)
print("TCPServer Waiting for client on port 7000")
while 1:
client_socket, address = server_socket.accept()
print("I got a connection from ", address)
while 1:
data = client_socket.recv(32)
if (data == 'q' or data == 'Q'):
client_socket.shutdown(socket.SHUT_RDWR)
client_socket.close()
break;
else:
print("RECEIVED:",data)
client_example.py:
# TCP client example
import socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(("localhost", 7000))
while 1:
data = input( "SEND( TYPE q or Q to Quit):" )
if (data != 'Q' and data != 'q'):
my_bytes = bytearray()
for c in data:
my_bytes.append(ord(c))
client_socket.send(my_bytes)
else:
client_socket.shutdown(socket.SHUT_RDWR)
client_socket.close()
break;
Well, I feel dumb that I solved this thing after 11 minutes of posting the question when I was unable to solve it for 2 hours...
The problem was that I was comparing data with the string 'q' which was correct in python 2 but in python 3 what is being sent are bytes, b'q' <> 'q' ...
Here is the corrected code:
server_example.py
#TCP server example
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(("", 7000))
server_socket.listen(5)
print("TCPServer Waiting for client on port 7000")
while 1:
client_socket, address = server_socket.accept()
print("I got a connection from ", address)
while 1:
data = client_socket.recv(32)
print("RECEIVED:",data)
if (data == b'q' or data == b'Q'):
## client_socket.shutdown(socket.SHUT_RDWR)
client_socket.close()
break;
break;
client_example.py
# TCP client example
import socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(("localhost", 7000))
while 1:
data = input( "SEND( TYPE q or Q to Quit):" )
if (data != 'Q' and data != 'q'):
my_bytes = bytearray()
for c in data:
my_bytes.append(ord(c))
client_socket.send(my_bytes)
else:
my_bytes = bytearray()
my_bytes.append(ord(data))
client_socket.send(my_bytes)
## client_socket.shutdown(socket.SHUT_RDWR)
client_socket.close()
break;
You're assuming you're going to get the Q. You should also engage in the same processing when you get EOS from read, whatever form that takes in Python.
#EJP : By EOS you mean end of stream? If so you are right, this example was a very simple one to get started in which I overlooked details like these.
Anyway I found that using this check in the server it is solved:
data = input( "SEND( TYPE q or Q to Quit):" )
if (data == b''):
break;
I need a program that can create pre-defined shapes on screen according to that commands I send to it via TCP.
I'm trying to listen to a port and so that I can use them. Before waiting of a command (via network) I have the commands required to create a square (I plan to change its attributes via network commands)
The problem is it is not creating any graphics or opening the window as it should be..
require "socket"
require "mime"
require "ltn12"
host = "localhost"
port = "8080"
server, error = socket.bind(host, port)
if not server then print("server: " .. tostring(error)) os.exit() end
screen=MOAISim.openWindow ( "test", 640, 640 )
viewport = MOAIViewport.new (screen)
viewport:setSize ( 640, 640 )
viewport:setScale ( 640, 640 )
layer = MOAILayer2D.new ()
layer:setViewport ( viewport )
MOAISim.pushRenderPass ( layer )
function fillSquare (x,y,radius,red,green,blue)
a = red/255
b = green/255
c = blue/255
MOAIGfxDevice.setPenColor ( a, b, c) -- green
MOAIGfxDevice.setPenWidth ( 2 )
MOAIDraw.fillCircle ( x, y, radius, 4 ) -- x,y,r,steps
end
function onDraw ( )
fillSquare(0,64,64, 0,0,255)
end
scriptDeck = MOAIScriptDeck.new ()
scriptDeck:setRect ( -64, -64, 64, 64 )
scriptDeck:setDrawCallback ( onDraw)
prop = MOAIProp2D.new ()
prop:setDeck ( scriptDeck )
layer:insertProp ( prop )
while 1 do
print("server: waiting for client command...")
control = server:accept()
command, error = control:receive()
print(command,error)
error = control:send("hi from Moai\n")
end
It is waiting of the command from client at control = server:accept() but it is not opening up the graphics window as it should.. Is there any command to force it to open or render
Thank you
MOAI doesn't run your scripts in a separate thread. A blocking call (server:accept) or forever loop (while true do) will block your MOAI app and it will appear to freeze while it merrily sits in your script forever.
So you have to do two things:
Use non-blocking calls. In this case, you need to set your server's timeout to 0. That makes server:accept return immediately. Check it's return value to see if you got a connection.
Put your while loop in a coroutine and yield once per iteration.
You'll need to handle the client the same way, using non-blocking calls in a coroutine loop.
function clientProc(client)
print('client connected:', client)
client:settimeout(0) -- make client socket reads non-blocking
while true do
local command, err = client:receive('*l')
if command then
print('received command:', command)
err = client:send("hi from Moai\n")
elseif err == 'closed' then
print('client disconnected:', client)
break
elseif err ~= 'timeout' then
print('error: ', err)
break
end
coroutine.yield()
end
client:close()
end
function serverProc()
print("server: waiting for client connections...")
server:settimeout(0) -- make server:accept call non-blocking
while true do
local client = server:accept()
if client then
MOAICoroutine.new():run(clientProc, client)
end
coroutine.yield()
end
end
MOAICoroutine.new():run(serverProc)
Set the timeout for the server socket, since the accept is a blocking call.
server:settimeout(1)
Thanks Mud...I found that before u replied so the following coroutine works
function threadFunc()
local action
while 1 do
stat, control = server:accept()
--print(control,stat)
while 1 do
if stat then
command, error = stat:receive()
print("Comm: ", command, error)
if command then
stat:close()
print("server: closing connection...")
break
else
break
end
--[[
error = stat:send("hi")
if error then
stat:close()
print("server: closing connection...",error)
break
end ]] --
else
break
end
end
coroutine.yield()
end
end
That was very helpful though